home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Utilities / vim-5.1 / src / term.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-29  |  88.9 KB  |  3,652 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8. /*
  9.  *
  10.  * term.c: functions for controlling the terminal
  11.  *
  12.  * primitive termcap support for Amiga, MSDOS, and Win32 included
  13.  *
  14.  * NOTE: padding and variable substitution is not performed,
  15.  * when compiling without HAVE_TGETENT, we use tputs() and tgoto() dummies.
  16.  */
  17.  
  18. /*
  19.  * Some systems have a prototype for tgetstr() with (char *) instead of
  20.  * (char **). This define removes that prototype. We include our own prototype
  21.  * below.
  22.  */
  23.  
  24. #define tgetstr tgetstr_defined_wrong
  25. #include "vim.h"
  26.  
  27. #ifdef HAVE_TGETENT
  28. # ifdef HAVE_TERMIOS_H
  29. #  include <termios.h>        /* seems to be required for some Linux */
  30. # endif
  31. # ifdef HAVE_TERMCAP_H
  32. #  include <termcap.h>
  33. # endif
  34.  
  35. /*
  36.  * A few linux systems define outfuntype in termcap.h to be used as the third
  37.  * argument for tputs().
  38.  */
  39. # ifdef VMS
  40. #  define TPUTSFUNCAST
  41. # else
  42. #  ifdef HAVE_OUTFUNTYPE
  43. #   define TPUTSFUNCAST (outfuntype)
  44. #  else
  45. #   define TPUTSFUNCAST (int (*)())
  46. #  endif
  47. # endif
  48. #endif
  49.  
  50. #undef tgetstr
  51.  
  52. /*
  53.  * Here are the builtin termcap entries.  They are not stored as complete
  54.  * Tcarr structures, as such a structure is too big.
  55.  *
  56.  * The entries are compact, therefore they normally are included even when
  57.  * HAVE_TGETENT is defined. When HAVE_TGETENT is defined, the builtin entries
  58.  * can be accessed with "builtin_amiga", "builtin_ansi", "builtin_debug", etc.
  59.  *
  60.  * Each termcap is a list of builtin_term structures. It always starts with
  61.  * KS_NAME, which separates the entries.  See parse_builtin_tcap() for all
  62.  * details.
  63.  * bt_entry is either a KS_xxx code (< 0x100), or a K_xxx code.
  64.  */
  65. struct builtin_term
  66. {
  67.     int        bt_entry;
  68.     char    *bt_string;
  69. };
  70.  
  71. /* start of keys that are not directly used by Vim but can be mapped */
  72. #define BT_EXTRA_KEYS    0x101
  73.  
  74. static struct builtin_term *find_builtin_term __ARGS((char_u *name));
  75. static void parse_builtin_tcap __ARGS((char_u *s));
  76. static void term_color __ARGS((char_u *s, int n));
  77. static void gather_termleader __ARGS((void));
  78. static int get_bytes_from_buf __ARGS((char_u *, char_u *, int));
  79. static int term_is_builtin __ARGS((char_u *));
  80.  
  81. #ifdef HAVE_TGETENT
  82. static char_u *tgetent_error __ARGS((char_u *, char_u *));
  83.  
  84. /*
  85.  * Here is our own prototype for tgetstr(), any prototypes from the include
  86.  * files have been disabled by the define at the start of this file.
  87.  */
  88. char        *tgetstr __ARGS((char *, char **));
  89.  
  90. /*
  91.  * Don't declare these variables if termcap.h contains them.
  92.  * Autoconf checks if these variables should be declared extern (not all
  93.  * systems have them).
  94.  * Some versions define ospeed to be speed_t, but that is incompatible with
  95.  * BSD, where ospeed is short and speed_t is long.
  96.  */
  97. # ifndef HAVE_OSPEED
  98. #  ifdef OSPEED_EXTERN
  99. extern short ospeed;
  100. #   else
  101. short ospeed;
  102. #   endif
  103. # endif
  104. # ifndef HAVE_UP_BC_PC
  105. #  ifdef UP_BC_PC_EXTERN
  106. extern char *UP, *BC, PC;
  107. #  else
  108. char *UP, *BC, PC;
  109. #  endif
  110. # endif
  111.  
  112. # define TGETSTR(s, p)    (char_u *)tgetstr((s), (char **)(p))
  113. # define TGETENT(b, t)    tgetent((char *)(b), (char *)(t))
  114.  
  115. #endif /* HAVE_TGETENT */
  116.  
  117. struct builtin_term builtin_termcaps[] =
  118. {
  119.  
  120. #if defined(USE_GUI)
  121. /*
  122.  * Motif/Athena pseudo term-cap.
  123.  */
  124.     {(int)KS_NAME,    "gui"},
  125.     {(int)KS_CE,    "\033|$"},
  126.     {(int)KS_AL,    "\033|i"},
  127. # ifdef TERMINFO
  128.     {(int)KS_CAL,    "\033|%p1%dI"},
  129. # else
  130.     {(int)KS_CAL,    "\033|%dI"},
  131. # endif
  132.     {(int)KS_DL,    "\033|d"},
  133. # ifdef TERMINFO
  134.     {(int)KS_CDL,    "\033|%p1%dD"},
  135.     {(int)KS_CS,    "\033|%p1%d;%p2%dR"},
  136. # else
  137.     {(int)KS_CDL,    "\033|%dD"},
  138.     {(int)KS_CS,    "\033|%d;%dR"},
  139. # endif
  140.     {(int)KS_CL,    "\033|C"},
  141.     {(int)KS_ME,    "\033|31H"},    /* 31 = HL_ALL,        H = off */
  142.     {(int)KS_MR,    "\033|1h"},    /* 1  = HL_INVERSE,    h = on */
  143.     {(int)KS_MD,    "\033|2h"},    /* 2  = HL_BOLD,    h = on */
  144.     {(int)KS_SE,    "\033|16H"},    /* 16 = HL_STANDOUT,    H = off */
  145.     {(int)KS_SO,    "\033|16h"},    /* 16 = HL_STANDOUT,    h = on */
  146.     {(int)KS_UE,    "\033|8H"},    /* 8  = HL_UNDERLINE,    H = off */
  147.     {(int)KS_US,    "\033|8h"},    /* 8  = HL_UNDERLINE,    h = on */
  148.     {(int)KS_CZR,    "\033|4H"},    /* 4  = HL_ITALIC,    H = off */
  149.     {(int)KS_CZH,    "\033|4h"},    /* 4  = HL_ITALIC,    h = on */
  150.     {(int)KS_VB,    "\033|f"},
  151.     {(int)KS_MS,    "y"},
  152.     {(int)KS_LE,    "\010"},    /* cursur-left = BS */
  153.     {(int)KS_ND,    "\014"},    /* cursor-right = CTRL-L */
  154. # ifdef TERMINFO
  155.     {(int)KS_CM,    "\033|%p1%d;%p2%dM"},
  156. # else
  157.     {(int)KS_CM,    "\033|%d;%dM"},
  158. # endif
  159.     /* there are no key sequences here, the GUI sequences are recognized
  160.      * in check_termcodes() */
  161. #endif
  162.  
  163. #ifndef NO_BUILTIN_TCAPS
  164.  
  165. # if defined(AMIGA) || defined(ALL_BUILTIN_TCAPS)
  166. /*
  167.  * Amiga console window, default for Amiga
  168.  */
  169.     {(int)KS_NAME,    "amiga"},
  170.     {(int)KS_CE,    "\033[K"},
  171.     {(int)KS_CD,    "\033[J"},
  172.     {(int)KS_AL,    "\033[L"},
  173. #  ifdef TERMINFO
  174.     {(int)KS_CAL,    "\033[%p1%dL"},
  175. #  else
  176.     {(int)KS_CAL,    "\033[%dL"},
  177. #  endif
  178.     {(int)KS_DL,    "\033[M"},
  179. #  ifdef TERMINFO
  180.     {(int)KS_CDL,    "\033[%p1%dM"},
  181. #  else
  182.     {(int)KS_CDL,    "\033[%dM"},
  183. #  endif
  184.     {(int)KS_CL,    "\014"},
  185.     {(int)KS_VI,    "\033[0 p"},
  186.     {(int)KS_VE,    "\033[1 p"},
  187.     {(int)KS_ME,    "\033[0m"},
  188.     {(int)KS_MR,    "\033[7m"},
  189.     {(int)KS_MD,    "\033[1m"},
  190.     {(int)KS_SE,    "\033[0m"},
  191.     {(int)KS_SO,    "\033[33m"},
  192.     {(int)KS_US,    "\033[4m"},
  193.     {(int)KS_UE,    "\033[0m"},
  194.     {(int)KS_CZH,    "\033[3m"},
  195.     {(int)KS_CZR,    "\033[0m"},
  196.     {(int)KS_MS,    "y"},
  197.     {(int)KS_LE,    "\010"},
  198. #  ifdef TERMINFO
  199.     {(int)KS_CM,    "\033[%i%p1%d;%p2%dH"},
  200. #  else
  201.     {(int)KS_CM,    "\033[%i%d;%dH"},
  202. #  endif
  203. #  ifdef TERMINFO
  204.     {(int)KS_CRI,    "\033[%p1%dC"},
  205. #  else
  206.     {(int)KS_CRI,    "\033[%dC"},
  207. #  endif
  208.     {K_UP,        "\233A"},
  209.     {K_DOWN,        "\233B"},
  210.     {K_LEFT,        "\233D"},
  211.     {K_RIGHT,        "\233C"},
  212.     {K_S_UP,        "\233T"},
  213.     {K_S_DOWN,        "\233S"},
  214.     {K_S_LEFT,        "\233 A"},
  215.     {K_S_RIGHT,        "\233 @"},
  216.     {K_S_TAB,        "\233Z"},
  217.     {K_F1,        "\233\060~"},/* some compilers don't dig "\2330" */
  218.     {K_F2,        "\233\061~"},
  219.     {K_F3,        "\233\062~"},
  220.     {K_F4,        "\233\063~"},
  221.     {K_F5,        "\233\064~"},
  222.     {K_F6,        "\233\065~"},
  223.     {K_F7,        "\233\066~"},
  224.     {K_F8,        "\233\067~"},
  225.     {K_F9,        "\233\070~"},
  226.     {K_F10,        "\233\071~"},
  227.     {K_S_F1,        "\233\061\060~"},
  228.     {K_S_F2,        "\233\061\061~"},
  229.     {K_S_F3,        "\233\061\062~"},
  230.     {K_S_F4,        "\233\061\063~"},
  231.     {K_S_F5,        "\233\061\064~"},
  232.     {K_S_F6,        "\233\061\065~"},
  233.     {K_S_F7,        "\233\061\066~"},
  234.     {K_S_F8,        "\233\061\067~"},
  235.     {K_S_F9,        "\233\061\070~"},
  236.     {K_S_F10,        "\233\061\071~"},
  237.     {K_HELP,        "\233?~"},
  238.     {K_INS,        "\233\064\060~"},    /* 101 key keyboard */
  239.     {K_PAGEUP,        "\233\064\061~"},    /* 101 key keyboard */
  240.     {K_PAGEDOWN,    "\233\064\062~"},    /* 101 key keyboard */
  241.     {K_HOME,        "\233\064\064~"},    /* 101 key keyboard */
  242.     {K_END,        "\233\064\065~"},    /* 101 key keyboard */
  243.  
  244.     {BT_EXTRA_KEYS,    ""},
  245.     {TERMCAP2KEY('#', '2'), "\233\065\064~"},    /* shifted home key */
  246.     {TERMCAP2KEY('#', '3'), "\233\065\060~"},    /* shifted insert key */
  247.     {TERMCAP2KEY('*', '7'), "\233\065\065~"},    /* shifted end key */
  248. # endif
  249.  
  250. # if defined(__BEOS__) || defined(ALL_BUILTIN_TCAPS)
  251. /*
  252.  * almost standard ANSI terminal, default for bebox
  253.  */
  254.     {(int)KS_NAME,    "beos-ansi"},
  255.     {(int)KS_CE,    "\033[K"},
  256.     {(int)KS_CD,    "\033[J"},
  257.     {(int)KS_AL,    "\033[L"},
  258. #  ifdef TERMINFO
  259.     {(int)KS_CAL,    "\033[%p1%dL"},
  260. #  else
  261.     {(int)KS_CAL,    "\033[%dL"},
  262. #  endif
  263.     {(int)KS_DL,    "\033[M"},
  264. #  ifdef TERMINFO
  265.     {(int)KS_CDL,    "\033[%p1%dM"},
  266. #  else
  267.     {(int)KS_CDL,    "\033[%dM"},
  268. #  endif
  269. #ifdef BEOS_PR_OR_BETTER
  270. #  ifdef TERMINFO
  271.     {(int)KS_CS,    "\033[%i%p1%d;%p2%dr"},
  272. #  else
  273.     {(int)KS_CS,    "\033[%i%d;%dr"},    /* scroll region */
  274. #  endif
  275. #endif
  276.     {(int)KS_CL,    "\033[H\033[2J"},
  277. #ifdef notyet
  278.     {(int)KS_VI,    "[VI]"}, /* cursor invisible, VT320: CSI ? 25 l */
  279.     {(int)KS_VE,    "[VE]"}, /* cursor visible, VT320: CSI ? 25 h */
  280. #endif
  281.     {(int)KS_ME,    "\033[m"},    /* normal mode */
  282.     {(int)KS_MR,    "\033[7m"},    /* reverse */
  283.     {(int)KS_MD,    "\033[1m"},    /* bold */
  284.     {(int)KS_SO,    "\033[31m"},    /* standout mode: red */
  285.     {(int)KS_SE,    "\033[m"},    /* standout end */
  286.     {(int)KS_CZH,    "\033[35m"},    /* italic: purple */
  287.     {(int)KS_CZR,    "\033[m"},    /* italic end */
  288.     {(int)KS_US,    "\033[4m"},    /* underscore mode */
  289.     {(int)KS_UE,    "\033[m"},    /* underscore end */
  290.     {(int)KS_CCO,    "8"},        /* allow 8 colors */
  291. #  ifdef TERMINFO
  292.     {(int)KS_CAB,    "\033[4%p1%dm"},/* set background color */
  293.     {(int)KS_CAF,    "\033[3%p1%dm"},/* set foreground color */
  294. #  else
  295.     {(int)KS_CAB,    "\033[4%dm"},    /* set background color */
  296.     {(int)KS_CAF,    "\033[3%dm"},    /* set foreground color */
  297. #  endif
  298.     {(int)KS_OP,    "\033[m"},    /* reset colors */
  299.     {(int)KS_MS,    "y"},        /* safe to move cur in reverse mode */
  300.     {(int)KS_LE,    "\010"},
  301. #  ifdef TERMINFO
  302.     {(int)KS_CM,    "\033[%i%p1%d;%p2%dH"},
  303. #  else
  304.     {(int)KS_CM,    "\033[%i%d;%dH"},
  305. #  endif
  306.     {(int)KS_SR,    "\033M"},
  307. #  ifdef TERMINFO
  308.     {(int)KS_CRI,    "\033[%p1%dC"},
  309. #  else
  310.     {(int)KS_CRI,    "\033[%dC"},
  311. #  endif
  312. #if defined(BEOS_DR8)
  313.     {(int)KS_DB,    ""},        /* hack! see screen.c */
  314. #endif
  315.  
  316.     {K_UP,        "\033[A"},
  317.     {K_DOWN,        "\033[B"},
  318.     {K_LEFT,        "\033[D"},
  319.     {K_RIGHT,        "\033[C"},
  320. # endif
  321.  
  322. # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) || defined(__EMX__)
  323. /*
  324.  * standard ANSI terminal, default for unix
  325.  */
  326.     {(int)KS_NAME,    "ansi"},
  327.     {(int)KS_CE,    "\033[K"},
  328.     {(int)KS_AL,    "\033[L"},
  329. #  ifdef TERMINFO
  330.     {(int)KS_CAL,    "\033[%p1%dL"},
  331. #  else
  332.     {(int)KS_CAL,    "\033[%dL"},
  333. #  endif
  334.     {(int)KS_DL,    "\033[M"},
  335. #  ifdef TERMINFO
  336.     {(int)KS_CDL,    "\033[%p1%dM"},
  337. #  else
  338.     {(int)KS_CDL,    "\033[%dM"},
  339. #  endif
  340.     {(int)KS_CL,    "\033[H\033[2J"},
  341.     {(int)KS_ME,    "\033[0m"},
  342.     {(int)KS_MR,    "\033[7m"},
  343.     {(int)KS_MS,    "y"},
  344.     {(int)KS_LE,    "\010"},
  345. #  ifdef TERMINFO
  346.     {(int)KS_CM,    "\033[%i%p1%d;%p2%dH"},
  347. #  else
  348.     {(int)KS_CM,    "\033[%i%d;%dH"},
  349. #  endif
  350. #  ifdef TERMINFO
  351.     {(int)KS_CRI,    "\033[%p1%dC"},
  352. #  else
  353.     {(int)KS_CRI,    "\033[%dC"},
  354. #  endif
  355. # endif
  356.  
  357. # if defined(MSDOS) || defined(ALL_BUILTIN_TCAPS) || defined(__EMX__)
  358. /*
  359.  * These codes are valid when nansi.sys or equivalent has been installed.
  360.  * Function keys on a PC are preceded with a NUL. These are converted into
  361.  * K_NUL '\316' in mch_inchar(), because we cannot handle NULs in key codes.
  362.  * CTRL-arrow is used instead of SHIFT-arrow.
  363.  */
  364. #ifdef __EMX__
  365.     {(int)KS_NAME,    "os2ansi"},
  366. #else
  367.     {(int)KS_NAME,    "pcansi"},
  368.     {(int)KS_DL,    "\033[M"},
  369.     {(int)KS_AL,    "\033[L"},
  370. #endif
  371.     {(int)KS_CE,    "\033[K"},
  372.     {(int)KS_CL,    "\033[2J"},
  373.     {(int)KS_ME,    "\033[0m"},
  374.     {(int)KS_MR,    "\033[5m"},    /* reverse: black on lightgrey */
  375.     {(int)KS_MD,    "\033[1m"},    /* bold: white text */
  376.     {(int)KS_SE,    "\033[0m"},    /* standout end */
  377.     {(int)KS_SO,    "\033[31m"},    /* standout: white on blue */
  378.     {(int)KS_CZH,    "\033[34;43m"},    /* italic mode: blue text on yellow */
  379.     {(int)KS_CZR,    "\033[0m"},    /* italic mode end */
  380.     {(int)KS_US,    "\033[36;41m"},    /* underscore mode: cyan text on red */
  381.     {(int)KS_UE,    "\033[0m"},    /* underscore mode end */
  382.     {(int)KS_CCO,    "8"},        /* allow 8 colors */
  383. #  ifdef TERMINFO
  384.     {(int)KS_CAB,    "\033[4%p1%dm"},/* set background color */
  385.     {(int)KS_CAF,    "\033[3%p1%dm"},/* set foreground color */
  386. #  else
  387.     {(int)KS_CAB,    "\033[4%dm"},    /* set background color */
  388.     {(int)KS_CAF,    "\033[3%dm"},    /* set foreground color */
  389. #  endif
  390.     {(int)KS_OP,    "\033[0m"},    /* reset colors */
  391.     {(int)KS_MS,    "y"},
  392.     {(int)KS_LE,    "\010"},
  393. #  ifdef TERMINFO
  394.     {(int)KS_CM,    "\033[%i%p1%d;%p2%dH"},
  395. #  else
  396.     {(int)KS_CM,    "\033[%i%d;%dH"},
  397. #  endif
  398. #  ifdef TERMINFO
  399.     {(int)KS_CRI,    "\033[%p1%dC"},
  400. #  else
  401.     {(int)KS_CRI,    "\033[%dC"},
  402. #  endif
  403.     {K_UP,        "\316H"},
  404.     {K_DOWN,        "\316P"},
  405.     {K_LEFT,        "\316K"},
  406.     {K_RIGHT,        "\316M"},
  407.     {K_S_LEFT,        "\316s"},
  408.     {K_S_RIGHT,        "\316t"},
  409.     {K_F1,        "\316;"},
  410.     {K_F2,        "\316<"},
  411.     {K_F3,        "\316="},
  412.     {K_F4,        "\316>"},
  413.     {K_F5,        "\316?"},
  414.     {K_F6,        "\316@"},
  415.     {K_F7,        "\316A"},
  416.     {K_F8,        "\316B"},
  417.     {K_F9,        "\316C"},
  418.     {K_F10,        "\316D"},
  419.     {K_F11,        "\316\205"},    /* guessed */
  420.     {K_F12,        "\316\206"},    /* guessed */
  421.     {K_S_F1,        "\316T"},
  422.     {K_S_F2,        "\316U"},
  423.     {K_S_F3,        "\316V"},
  424.     {K_S_F4,        "\316W"},
  425.     {K_S_F5,        "\316X"},
  426.     {K_S_F6,        "\316Y"},
  427.     {K_S_F7,        "\316Z"},
  428.     {K_S_F8,        "\316["},
  429.     {K_S_F9,        "\316\\"},
  430.     {K_S_F10,        "\316]"},
  431.     {K_S_F11,        "\316\207"},    /* guessed */
  432.     {K_S_F12,        "\316\210"},    /* guessed */
  433.     {K_INS,        "\316R"},
  434.     {K_DEL,        "\316S"},
  435.     {K_HOME,        "\316G"},
  436.     {K_END,        "\316O"},
  437.     {K_PAGEDOWN,    "\316Q"},
  438.     {K_PAGEUP,        "\316I"},
  439. # endif
  440.  
  441. # if defined(MSDOS)
  442. /*
  443.  * These codes are valid for the pc video.  The entries that start with ESC |
  444.  * are translated into conio calls in os_msdos.c. Default for MSDOS.
  445.  */
  446.     {(int)KS_NAME,    "pcterm"},
  447.     {(int)KS_CE,    "\033|K"},
  448.     {(int)KS_AL,    "\033|L"},
  449.     {(int)KS_DL,    "\033|M"},
  450. #  ifdef TERMINFO
  451.     {(int)KS_CS,    "\033|%i%p1%d;%p2%dr"},
  452. #  else
  453.     {(int)KS_CS,    "\033|%i%d;%dr"},
  454. #  endif
  455.     {(int)KS_CL,    "\033|J"},
  456.     {(int)KS_ME,    "\033|0m"},    /* normal */
  457.     {(int)KS_MR,    "\033|112m"},    /* reverse: black on lightgrey */
  458.     {(int)KS_MD,    "\033|15m"},    /* bold: white text */
  459.     {(int)KS_SE,    "\033|0m"},    /* standout end */
  460.     {(int)KS_SO,    "\033|31m"},    /* standout: white on blue */
  461.     {(int)KS_CZH,    "\033|225m"},    /* italic mode: blue text on yellow */
  462.     {(int)KS_CZR,    "\033|0m"},    /* italic mode end */
  463.     {(int)KS_US,    "\033|67m"},    /* underscore mode: cyan text on red */
  464.     {(int)KS_UE,    "\033|0m"},    /* underscore mode end */
  465.     {(int)KS_CCO,    "16"},        /* allow 16 colors */
  466. #  ifdef TERMINFO
  467.     {(int)KS_CAB,    "\033|%p1%db"},    /* set background color */
  468.     {(int)KS_CAF,    "\033|%p1%df"},    /* set foreground color */
  469. #  else
  470.     {(int)KS_CAB,    "\033|%db"},    /* set background color */
  471.     {(int)KS_CAF,    "\033|%df"},    /* set foreground color */
  472. #  endif
  473.     {(int)KS_MS,    "y"},
  474.     {(int)KS_LE,    "\010"},
  475. #  ifdef TERMINFO
  476.     {(int)KS_CM,    "\033|%i%p1%d;%p2%dH"},
  477. #  else
  478.     {(int)KS_CM,    "\033|%i%d;%dH"},
  479. #  endif
  480. #ifdef DJGPP
  481.     {(int)KS_VB,    "\033|B"},    /* visual bell */
  482. #endif
  483.     {K_UP,        "\316H"},
  484.     {K_DOWN,        "\316P"},
  485.     {K_LEFT,        "\316K"},
  486.     {K_RIGHT,        "\316M"},
  487.     {K_S_LEFT,        "\316s"},
  488.     {K_S_RIGHT,        "\316t"},
  489.     {K_S_TAB,        "\316\017"},
  490.     {K_F1,        "\316;"},
  491.     {K_F2,        "\316<"},
  492.     {K_F3,        "\316="},
  493.     {K_F4,        "\316>"},
  494.     {K_F5,        "\316?"},
  495.     {K_F6,        "\316@"},
  496.     {K_F7,        "\316A"},
  497.     {K_F8,        "\316B"},
  498.     {K_F9,        "\316C"},
  499.     {K_F10,        "\316D"},
  500.     {K_F11,        "\316\205"},    /* only when nobioskey */
  501.     {K_F12,        "\316\206"},    /* only when nobioskey */
  502.     {K_S_F1,        "\316T"},
  503.     {K_S_F2,        "\316U"},
  504.     {K_S_F3,        "\316V"},
  505.     {K_S_F4,        "\316W"},
  506.     {K_S_F5,        "\316X"},
  507.     {K_S_F6,        "\316Y"},
  508.     {K_S_F7,        "\316Z"},
  509.     {K_S_F8,        "\316["},
  510.     {K_S_F9,        "\316\\"},
  511.     {K_S_F10,        "\316]"},
  512.     {K_S_F11,        "\316\207"},    /* only when nobioskey */
  513.     {K_S_F12,        "\316\210"},    /* only when nobioskey */
  514.     {K_INS,        "\316R"},
  515.     {K_DEL,        "\316S"},
  516.     {K_HOME,        "\316G"},
  517.     {K_END,        "\316O"},
  518.     {K_PAGEDOWN,    "\316Q"},
  519.     {K_PAGEUP,        "\316I"},
  520. # endif
  521.  
  522. # if defined(WIN32) || defined(ALL_BUILTIN_TCAPS) || defined(__EMX__)
  523. /*
  524.  * These codes are valid for the Win32 Console .  The entries that start with
  525.  * ESC | are translated into console calls in os_win32.c.  The function keys
  526.  * are also translated in os_win32.c.
  527.  */
  528.     {(int)KS_NAME,    "win32"},
  529.     {(int)KS_CE,    "\033|K"},    /* clear to end of line */
  530.     {(int)KS_AL,    "\033|L"},    /* add new blank line */
  531. #  ifdef TERMINFO
  532.     {(int)KS_CAL,    "\033|%p1%dL"},    /* add number of new blank lines */
  533. #  else
  534.     {(int)KS_CAL,    "\033|%dL"},    /* add number of new blank lines */
  535. #  endif
  536.     {(int)KS_DL,    "\033|M"},    /* delete line */
  537. #  ifdef TERMINFO
  538.     {(int)KS_CDL,    "\033|%p1%dM"},    /* delete number of lines */
  539. #  else
  540.     {(int)KS_CDL,    "\033|%dM"},    /* delete number of lines */
  541. #  endif
  542.     {(int)KS_CL,    "\033|J"},    /* clear screen */
  543.     {(int)KS_CD,    "\033|j"},    /* clear to end of display */
  544.     {(int)KS_VI,    "\033|v"},    /* cursor invisible */
  545.     {(int)KS_VE,    "\033|V"},    /* cursor visible */
  546.  
  547.     {(int)KS_ME,    "\033|0m"},    /* normal */
  548.     {(int)KS_MR,    "\033|112m"},    /* reverse: black on lightgray */
  549.     {(int)KS_MD,    "\033|15m"},    /* bold: white on black */
  550. #if 1
  551.     {(int)KS_SO,    "\033|31m"},    /* standout: white on blue */
  552.     {(int)KS_SE,    "\033|0m"},    /* standout end */
  553. #else
  554.     {(int)KS_SO,    "\033|F"},    /* standout: high intensity */
  555.     {(int)KS_SE,    "\033|f"},    /* standout end */
  556. #endif
  557.     {(int)KS_CZH,    "\033|225m"},    /* italic: blue text on yellow */
  558.     {(int)KS_CZR,    "\033|0m"},    /* italic end */
  559.     {(int)KS_US,    "\033|67m"},    /* underscore: cyan text on red */
  560.     {(int)KS_UE,    "\033|0m"},    /* underscore end */
  561.     {(int)KS_CCO,    "16"},        /* allow 16 colors */
  562. #  ifdef TERMINFO
  563.     {(int)KS_CAB,    "\033|%p1%db"},    /* set background color */
  564.     {(int)KS_CAF,    "\033|%p1%df"},    /* set foreground color */
  565. #  else
  566.     {(int)KS_CAB,    "\033|%db"},    /* set background color */
  567.     {(int)KS_CAF,    "\033|%df"},    /* set foreground color */
  568. #  endif
  569.  
  570.     {(int)KS_MS,    "y"},        /* save to move cur in reverse mode */
  571.     {(int)KS_LE,    "\010"},
  572. #  ifdef TERMINFO
  573.     {(int)KS_CM,    "\033|%i%p1%d;%p2%dH"},/* cursor motion */
  574. #  else
  575.     {(int)KS_CM,    "\033|%i%d;%dH"},/* cursor motion */
  576. #  endif
  577.     {(int)KS_VB,    "\033|B"},    /* visual bell */
  578.     {(int)KS_TI,    "\033|S"},    /* put terminal in termcap mode */
  579.     {(int)KS_TE,    "\033|E"},    /* out of termcap mode */
  580.     {(int)KS_CS,    "\033|%i%d;%dr"},/* scroll region */
  581.  
  582.     {K_UP,        "\316H"},
  583.     {K_DOWN,        "\316P"},
  584.     {K_LEFT,        "\316K"},
  585.     {K_RIGHT,        "\316M"},
  586.     {K_S_UP,        "\316\304"},
  587.     {K_S_DOWN,        "\316\317"},
  588.     {K_S_LEFT,        "\316\311"},
  589.     {K_S_RIGHT,        "\316\313"},
  590.     {K_S_TAB,        "\316\017"},
  591.     {K_F1,        "\316;"},
  592.     {K_F2,        "\316<"},
  593.     {K_F3,        "\316="},
  594.     {K_F4,        "\316>"},
  595.     {K_F5,        "\316?"},
  596.     {K_F6,        "\316@"},
  597.     {K_F7,        "\316A"},
  598.     {K_F8,        "\316B"},
  599.     {K_F9,        "\316C"},
  600.     {K_F10,        "\316D"},
  601.     {K_F11,        "\316\205"},
  602.     {K_F12,        "\316\206"},
  603.     {K_S_F1,        "\316T"},
  604.     {K_S_F2,        "\316U"},
  605.     {K_S_F3,        "\316V"},
  606.     {K_S_F4,        "\316W"},
  607.     {K_S_F5,        "\316X"},
  608.     {K_S_F6,        "\316Y"},
  609.     {K_S_F7,        "\316Z"},
  610.     {K_S_F8,        "\316["},
  611.     {K_S_F9,        "\316\\"},
  612.     {K_S_F10,        "\316]"},
  613.     {K_S_F11,        "\316\207"},
  614.     {K_S_F12,        "\316\210"},
  615.     {K_INS,        "\316R"},
  616.     {K_DEL,        "\316S"},
  617.     {K_HOME,        "\316G"},
  618.     {K_END,        "\316O"},
  619.     {K_PAGEDOWN,    "\316Q"},
  620.     {K_PAGEUP,        "\316I"},
  621. # endif
  622.  
  623. # if defined(ALL_BUILTIN_TCAPS) || defined(__MINT__)
  624. /*
  625.  * Ordinary vt52
  626.  */
  627.     {(int)KS_NAME,    "vt52"},
  628.     {(int)KS_CE,    "\033K"},
  629.     {(int)KS_CD,    "\033J"},
  630.     {(int)KS_CM,    "\033Y%+ %+ "},
  631.     {(int)KS_LE,    "\010"},
  632. #  ifdef __MINT__
  633.     {(int)KS_AL,    "\033L"},
  634.     {(int)KS_DL,    "\033M"},
  635.     {(int)KS_CL,    "\033E"},
  636.     {(int)KS_SR,    "\033I"},
  637.     {(int)KS_VE,    "\033e"},
  638.     {(int)KS_VI,    "\033f"},
  639.     {(int)KS_SO,    "\033p"},
  640.     {(int)KS_SE,    "\033q"},
  641.     {K_UP,        "\033A"},
  642.     {K_DOWN,        "\033B"},
  643.     {K_LEFT,        "\033D"},
  644.     {K_RIGHT,        "\033C"},
  645.     {K_S_UP,        "\033a"},
  646.     {K_S_DOWN,        "\033b"},
  647.     {K_S_LEFT,        "\033d"},
  648.     {K_S_RIGHT,        "\033c"},
  649.     {K_F1,        "\033P"},
  650.     {K_F2,        "\033Q"},
  651.     {K_F3,        "\033R"},
  652.     {K_F4,        "\033S"},
  653.     {K_F5,        "\033T"},
  654.     {K_F6,        "\033U"},
  655.     {K_F7,        "\033V"},
  656.     {K_F8,        "\033W"},
  657.     {K_F9,        "\033X"},
  658.     {K_F10,        "\033Y"},
  659.     {K_S_F1,        "\033p"},
  660.     {K_S_F2,        "\033q"},
  661.     {K_S_F3,        "\033r"},
  662.     {K_S_F4,        "\033s"},
  663.     {K_S_F5,        "\033t"},
  664.     {K_S_F6,        "\033u"},
  665.     {K_S_F7,        "\033v"},
  666.     {K_S_F8,        "\033w"},
  667.     {K_S_F9,        "\033x"},
  668.     {K_S_F10,        "\033y"},
  669.     {K_INS,        "\033I"},
  670.     {K_HOME,        "\033E"},
  671.     {K_PAGEDOWN,    "\033b"},
  672.     {K_PAGEUP,        "\033a"},
  673. #  else
  674.     {(int)KS_AL,    "\033T"},
  675.     {(int)KS_DL,    "\033U"},
  676.     {(int)KS_CL,    "\033H\033J"},
  677.     {(int)KS_ME,    "\033SO"},
  678.     {(int)KS_MR,    "\033S2"},
  679.     {(int)KS_MS,    "y"},
  680. #  endif
  681. # endif
  682.  
  683. # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) || defined(__EMX__)
  684. /*
  685.  * The xterm termcap is missing F14 and F15, because they send the same
  686.  * codes as the undo and help key, although they don't work on all keyboards.
  687.  */
  688.     {(int)KS_NAME,    "xterm"},
  689.     {(int)KS_CE,    "\033[K"},
  690.     {(int)KS_AL,    "\033[L"},
  691. #  ifdef TERMINFO
  692.     {(int)KS_CAL,    "\033[%p1%dL"},
  693. #  else
  694.     {(int)KS_CAL,    "\033[%dL"},
  695. #  endif
  696.     {(int)KS_DL,    "\033[M"},
  697. #  ifdef TERMINFO
  698.     {(int)KS_CDL,    "\033[%p1%dM"},
  699. #  else
  700.     {(int)KS_CDL,    "\033[%dM"},
  701. #  endif
  702. #  ifdef TERMINFO
  703.     {(int)KS_CS,    "\033[%i%p1%d;%p2%dr"},
  704. #  else
  705.     {(int)KS_CS,    "\033[%i%d;%dr"},
  706. #  endif
  707.     {(int)KS_CL,    "\033[H\033[2J"},
  708.     {(int)KS_CD,    "\033[J"},
  709.     {(int)KS_ME,    "\033[m"},
  710.     {(int)KS_MR,    "\033[7m"},
  711.     {(int)KS_MD,    "\033[1m"},
  712.     {(int)KS_UE,    "\033[m"},
  713.     {(int)KS_US,    "\033[4m"},
  714.     {(int)KS_MS,    "y"},
  715.     {(int)KS_LE,    "\010"},
  716. #  ifdef TERMINFO
  717.     {(int)KS_CM,    "\033[%i%p1%d;%p2%dH"},
  718. #  else
  719.     {(int)KS_CM,    "\033[%i%d;%dH"},
  720. #  endif
  721.     {(int)KS_SR,    "\033M"},
  722. #  ifdef TERMINFO
  723.     {(int)KS_CRI,    "\033[%p1%dC"},
  724. #  else
  725.     {(int)KS_CRI,    "\033[%dC"},
  726. #  endif
  727.     {(int)KS_KS,    "\033[?1h\033="},
  728.     {(int)KS_KE,    "\033[?1l\033>"},
  729. #  ifdef SAVE_XTERM_SCREEN
  730.     {(int)KS_TI,    "\0337\033[?47h"},
  731.     {(int)KS_TE,    "\033[2J\033[?47l\0338"},
  732. #  endif
  733.     {K_UP,        "\033OA"},
  734.     {K_DOWN,        "\033OB"},
  735.     {K_LEFT,        "\033OD"},
  736.     {K_RIGHT,        "\033OC"},
  737.     {K_S_UP,        "\033Ox"},
  738.     {K_S_DOWN,        "\033Or"},
  739.     {K_S_LEFT,        "\033Ot"},
  740.     {K_S_RIGHT,        "\033Ov"},
  741.     /* An extra set of function keys for vt100 mode */
  742.     {K_XF1,        "\033OP"},
  743.     {K_XF2,        "\033OQ"},
  744.     {K_XF3,        "\033OR"},
  745.     {K_XF4,        "\033OS"},
  746.     {K_F1,        "\033[11~"},
  747.     {K_F2,        "\033[12~"},
  748.     {K_F3,        "\033[13~"},
  749.     {K_F4,        "\033[14~"},
  750.     {K_F5,        "\033[15~"},
  751.     {K_F6,        "\033[17~"},
  752.     {K_F7,        "\033[18~"},
  753.     {K_F8,        "\033[19~"},
  754.     {K_F9,        "\033[20~"},
  755.     {K_F10,        "\033[21~"},
  756.     {K_F11,        "\033[23~"},
  757.     {K_F12,        "\033[24~"},
  758.     {K_HELP,        "\033[28~"},
  759.     {K_UNDO,        "\033[26~"},
  760.     {K_INS,        "\033[2~"},
  761.     {K_HOME,        "\033[7~"},
  762.     {K_KHOME,        "\033[1~"},
  763.     {K_END,        "\033[8~"},
  764.     {K_KEND,        "\033[4~"},
  765.     {K_PAGEUP,        "\033[5~"},
  766.     {K_PAGEDOWN,    "\033[6~"},
  767.     /* {K_DEL,        "\033[3~"}, not used */
  768.  
  769.     {BT_EXTRA_KEYS,   ""},
  770.     {TERMCAP2KEY('k', '0'),    "\033[10~"},    /* F0 */
  771.     {TERMCAP2KEY('F', '3'),    "\033[25~"},    /* F13 */
  772.     {TERMCAP2KEY('F', '6'),    "\033[29~"},    /* F16 */
  773.     {TERMCAP2KEY('F', '7'),    "\033[31~"},    /* F17 */
  774.     {TERMCAP2KEY('F', '8'),    "\033[32~"},    /* F18 */
  775.     {TERMCAP2KEY('F', '9'),    "\033[33~"},    /* F19 */
  776.     {TERMCAP2KEY('F', 'A'),    "\033[34~"},    /* F20 */
  777. # endif
  778.  
  779. # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS)
  780. /*
  781.  * iris-ansi for Silicon Graphics machines.
  782.  */
  783.     {(int)KS_NAME,    "iris-ansi"},
  784.     {(int)KS_CE,    "\033[K"},
  785.     {(int)KS_CD,    "\033[J"},
  786.     {(int)KS_AL,    "\033[L"},
  787. #  ifdef TERMINFO
  788.     {(int)KS_CAL,    "\033[%p1%dL"},
  789. #  else
  790.     {(int)KS_CAL,    "\033[%dL"},
  791. #  endif
  792.     {(int)KS_DL,    "\033[M"},
  793. #  ifdef TERMINFO
  794.     {(int)KS_CDL,    "\033[%p1%dM"},
  795. #  else
  796.     {(int)KS_CDL,    "\033[%dM"},
  797. #  endif
  798. /*
  799.  * This "cs" is not working correctly. What is the right one?
  800.  */
  801. #if 0
  802. #  ifdef TERMINFO
  803.     {(int)KS_CS,    "\033[%i%p1%d;%p2%dr"},
  804. #  else
  805.      {(int)KS_CS,    "\033[%i%d;%dr"},
  806. #  endif
  807. #endif
  808.     {(int)KS_CL,    "\033[H\033[2J"},
  809.     {(int)KS_VE,    "\033[9/y\033[12/y\033[=6l"},
  810.     {(int)KS_VS,    "\033[10/y\033[=1h\033[=2l\033[=6h"},
  811.     {(int)KS_SE,    "\033[m"},
  812.     {(int)KS_SO,    "\033[1;7m"},
  813.     {(int)KS_ME,    "\033[m"},
  814.     {(int)KS_MR,    "\033[7m"},
  815.     {(int)KS_MD,    "\033[1m"},
  816.     {(int)KS_UE,    "\033[m"},
  817.     {(int)KS_US,    "\033[4m"},
  818.     {(int)KS_MS,    "y"},    /* does this really work? */
  819.     {(int)KS_LE,    "\010"},
  820. #  ifdef TERMINFO
  821.     {(int)KS_CM,    "\033[%i%p1%d;%p2%dH"},
  822. #  else
  823.     {(int)KS_CM,    "\033[%i%d;%dH"},
  824. #  endif
  825.     {(int)KS_SR,    "\033M"},
  826. #  ifdef TERMINFO
  827.     {(int)KS_CRI,    "\033[%p1%dC"},
  828. #  else
  829.     {(int)KS_CRI,    "\033[%dC"},
  830. #  endif
  831.     {K_UP,        "\033[A"},
  832.     {K_DOWN,        "\033[B"},
  833.     {K_LEFT,        "\033[D"},
  834.     {K_RIGHT,        "\033[C"},
  835.     {K_S_UP,        "\033[161q"},
  836.     {K_S_DOWN,        "\033[164q"},
  837.     {K_S_LEFT,        "\033[158q"},
  838.     {K_S_RIGHT,        "\033[167q"},
  839.     {K_F1,        "\033[001q"},
  840.     {K_F2,        "\033[002q"},
  841.     {K_F3,        "\033[003q"},
  842.     {K_F4,        "\033[004q"},
  843.     {K_F5,        "\033[005q"},
  844.     {K_F6,        "\033[006q"},
  845.     {K_F7,        "\033[007q"},
  846.     {K_F8,        "\033[008q"},
  847.     {K_F9,        "\033[009q"},
  848.     {K_F10,        "\033[010q"},
  849.     {K_F11,        "\033[011q"},
  850.     {K_F12,        "\033[012q"},
  851.     {K_S_F1,        "\033[013q"},
  852.     {K_S_F2,        "\033[014q"},
  853.     {K_S_F3,        "\033[015q"},
  854.     {K_S_F4,        "\033[016q"},
  855.     {K_S_F5,        "\033[017q"},
  856.     {K_S_F6,        "\033[018q"},
  857.     {K_S_F7,        "\033[019q"},
  858.     {K_S_F8,        "\033[020q"},
  859.     {K_S_F9,        "\033[021q"},
  860.     {K_S_F10,        "\033[022q"},
  861.     {K_S_F11,        "\033[023q"},
  862.     {K_S_F12,        "\033[024q"},
  863.     {K_INS,        "\033[139q"},
  864.     {K_HOME,        "\033[H"},
  865.     {K_END,        "\033[146q"},
  866.     {K_PAGEUP,        "\033[150q"},
  867.     {K_PAGEDOWN,    "\033[154q"},
  868. # endif
  869.  
  870. # if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS)
  871. /*
  872.  * for debugging
  873.  */
  874.     {(int)KS_NAME,    "debug"},
  875.     {(int)KS_CE,    "[CE]"},
  876.     {(int)KS_CD,    "[CD]"},
  877.     {(int)KS_AL,    "[AL]"},
  878. #  ifdef TERMINFO
  879.     {(int)KS_CAL,    "[CAL%p1%d]"},
  880. #  else
  881.     {(int)KS_CAL,    "[CAL%d]"},
  882. #  endif
  883.     {(int)KS_DL,    "[DL]"},
  884. #  ifdef TERMINFO
  885.     {(int)KS_CDL,    "[CDL%p1%d]"},
  886. #  else
  887.     {(int)KS_CDL,    "[CDL%d]"},
  888. #  endif
  889. #  ifdef TERMINFO
  890.     {(int)KS_CS,    "[%dCS%p1%d]"},
  891. #  else
  892.     {(int)KS_CS,    "[%dCS%d]"},
  893. #  endif
  894. #  ifdef TERMINFO
  895.     {(int)KS_CAB,    "[CAB%p1%d]"},
  896.     {(int)KS_CAF,    "[CAF%p1%d]"},
  897.     {(int)KS_CSB,    "[CSB%p1%d]"},
  898.     {(int)KS_CSF,    "[CSF%p1%d]"},
  899. #  else
  900.     {(int)KS_CAB,    "[CAB%d]"},
  901.     {(int)KS_CAF,    "[CAF%d]"},
  902.     {(int)KS_CSB,    "[CSB%d]"},
  903.     {(int)KS_CSF,    "[CSF%d]"},
  904. #  endif
  905.     {(int)KS_OP,    "[OP]"},
  906.     {(int)KS_LE,    "[LE]"},
  907.     {(int)KS_CL,    "[CL]"},
  908.     {(int)KS_VI,    "[VI]"},
  909.     {(int)KS_VE,    "[VE]"},
  910.     {(int)KS_VS,    "[VS]"},
  911.     {(int)KS_ME,    "[ME]"},
  912.     {(int)KS_MR,    "[MR]"},
  913.     {(int)KS_MB,    "[MB]"},
  914.     {(int)KS_MD,    "[MD]"},
  915.     {(int)KS_SE,    "[SE]"},
  916.     {(int)KS_SO,    "[SO]"},
  917.     {(int)KS_UE,    "[UE]"},
  918.     {(int)KS_US,    "[US]"},
  919.     {(int)KS_MS,    "[MS]"},
  920. #  ifdef TERMINFO
  921.     {(int)KS_CM,    "[%p1%dCM%p2%d]"},
  922. #  else
  923.     {(int)KS_CM,    "[%dCM%d]"},
  924. #  endif
  925.     {(int)KS_SR,    "[SR]"},
  926. #  ifdef TERMINFO
  927.     {(int)KS_CRI,    "[CRI%p1%d]"},
  928. #  else
  929.     {(int)KS_CRI,    "[CRI%d]"},
  930. #  endif
  931.     {(int)KS_VB,    "[VB]"},
  932.     {(int)KS_KS,    "[KS]"},
  933.     {(int)KS_KE,    "[KE]"},
  934.     {(int)KS_TI,    "[TI]"},
  935.     {(int)KS_TE,    "[TE]"},
  936.     {K_UP,        "[KU]"},
  937.     {K_DOWN,        "[KD]"},
  938.     {K_LEFT,        "[KL]"},
  939.     {K_RIGHT,        "[KR]"},
  940.     {K_S_UP,        "[S-KU]"},
  941.     {K_S_DOWN,        "[S-KD]"},
  942.     {K_S_LEFT,        "[S-KL]"},
  943.     {K_S_RIGHT,        "[S-KR]"},
  944.     {K_F1,        "[F1]"},
  945.     {K_F2,        "[F2]"},
  946.     {K_F3,        "[F3]"},
  947.     {K_F4,        "[F4]"},
  948.     {K_F5,        "[F5]"},
  949.     {K_F6,        "[F6]"},
  950.     {K_F7,        "[F7]"},
  951.     {K_F8,        "[F8]"},
  952.     {K_F9,        "[F9]"},
  953.     {K_F10,        "[F10]"},
  954.     {K_F11,        "[F11]"},
  955.     {K_F12,        "[F12]"},
  956.     {K_S_F1,        "[S-F1]"},
  957.     {K_S_F2,        "[S-F2]"},
  958.     {K_S_F3,        "[S-F3]"},
  959.     {K_S_F4,        "[S-F4]"},
  960.     {K_S_F5,        "[S-F5]"},
  961.     {K_S_F6,        "[S-F6]"},
  962.     {K_S_F7,        "[S-F7]"},
  963.     {K_S_F8,        "[S-F8]"},
  964.     {K_S_F9,        "[S-F9]"},
  965.     {K_S_F10,        "[S-F10]"},
  966.     {K_S_F11,        "[S-F11]"},
  967.     {K_S_F12,        "[S-F12]"},
  968.     {K_HELP,        "[HELP]"},
  969.     {K_UNDO,        "[UNDO]"},
  970.     {K_BS,        "[BS]"},
  971.     {K_INS,        "[INS]"},
  972.     {K_DEL,        "[DEL]"},
  973.     {K_HOME,        "[HOME]"},
  974.     {K_END,        "[END]"},
  975.     {K_PAGEUP,        "[PAGEUP]"},
  976.     {K_PAGEDOWN,    "[PAGEDOWN]"},
  977.     {K_KHOME,        "[KHOME]"},
  978.     {K_KEND,        "[KEND]"},
  979.     {K_KPAGEUP,        "[KPAGEUP]"},
  980.     {K_KPAGEDOWN,    "[KPAGEDOWN]"},
  981.     {K_MOUSE,        "[MOUSE]"},
  982. # endif
  983.  
  984. #endif /* NO_BUILTIN_TCAPS */
  985.  
  986. /*
  987.  * The most minimal terminal: only clear screen and cursor positioning
  988.  * Always included.
  989.  */
  990.     {(int)KS_NAME,    "dumb"},
  991.     {(int)KS_CL,    "\014"},
  992. #ifdef TERMINFO
  993.     {(int)KS_CM,    "\033[%i%p1%d;%p2%dH"},
  994. #else
  995.     {(int)KS_CM,    "\033[%i%d;%dH"},
  996. #endif
  997.  
  998. /*
  999.  * end marker
  1000.  */
  1001.     {(int)KS_NAME,    NULL}
  1002.  
  1003. };    /* end of builtin_termcaps */
  1004.  
  1005. /*
  1006.  * DEFAULT_TERM is used, when no terminal is specified with -T option or $TERM.
  1007.  */
  1008. #ifdef AMIGA
  1009. # define DEFAULT_TERM    (char_u *)"amiga"
  1010. #endif
  1011.  
  1012. #ifdef WIN32
  1013. # define DEFAULT_TERM    (char_u *)"win32"
  1014. #endif
  1015.  
  1016. #ifdef MSDOS
  1017. # define DEFAULT_TERM    (char_u *)"pcterm"
  1018. #endif
  1019.  
  1020. #if defined(UNIX) && !defined(__MINT__)
  1021. # define DEFAULT_TERM    (char_u *)"ansi"
  1022. #endif
  1023.  
  1024. #ifdef __MINT__
  1025. # define DEFAULT_TERM    (char_u *)"vt52"
  1026. #endif
  1027.  
  1028. #ifdef __EMX__
  1029. # define DEFAULT_TERM    (char_u *)"os2ansi"
  1030. #endif
  1031.  
  1032. #ifdef VMS
  1033. # define DEFAULT_TERM    (char_u *)"ansi"
  1034. #endif
  1035.  
  1036. #ifdef __BEOS__
  1037. # undef DEFAULT_TERM
  1038. # define DEFAULT_TERM    (char_u *)"beos-ansi"
  1039. #endif
  1040.  
  1041. #ifdef macintosh
  1042. # define DEFAULT_TERM    (char_u *)"mac-ansi"
  1043. #endif
  1044.  
  1045. /*
  1046.  * Term_strings contains currently used terminal output strings.
  1047.  * It is initialized with the default values by parse_builtin_tcap().
  1048.  * The values can be changed by setting the option with the same name.
  1049.  */
  1050. char_u *(term_strings[(int)KS_LAST + 1]);
  1051.  
  1052. static int    need_gather = FALSE;        /* need to fill termleader[] */
  1053. static char_u    termleader[256 + 1];        /* for check_termcode() */
  1054.  
  1055.     static struct builtin_term *
  1056. find_builtin_term(term)
  1057.     char_u    *term;
  1058. {
  1059.     struct builtin_term *p;
  1060.  
  1061.     p = builtin_termcaps;
  1062.     while (p->bt_string != NULL)
  1063.     {
  1064.     if (p->bt_entry == (int)KS_NAME)
  1065.     {
  1066. #ifdef UNIX
  1067.         if (STRCMP(p->bt_string, "iris-ansi") == 0
  1068.                             && vim_is_iris_ansi(term))
  1069.         return p;
  1070.         else if (STRCMP(p->bt_string, "xterm") == 0 && vim_is_xterm(term))
  1071.         return p;
  1072.         else
  1073. #endif
  1074.         if (STRCMP(term, p->bt_string) == 0)
  1075.             return p;
  1076.     }
  1077.     ++p;
  1078.     }
  1079.     return p;
  1080. }
  1081.  
  1082. /*
  1083.  * Parsing of the builtin termcap entries.
  1084.  * Caller should check if 'name' is a valid builtin term.
  1085.  * The terminal's name is not set, as this is already done in termcapinit().
  1086.  */
  1087.     static void
  1088. parse_builtin_tcap(term)
  1089.     char_u  *term;
  1090. {
  1091.     struct builtin_term        *p;
  1092.     char_u            name[2];
  1093.  
  1094.     p = find_builtin_term(term);
  1095.     for (++p; p->bt_entry != (int)KS_NAME && p->bt_entry != BT_EXTRA_KEYS; ++p)
  1096.     {
  1097.     if ((int)p->bt_entry < 0x100)    /* KS_xx entry */
  1098.     {
  1099.         if (term_strings[p->bt_entry] == NULL ||
  1100.                     term_strings[p->bt_entry] == empty_option)
  1101.         term_strings[p->bt_entry] = (char_u *)p->bt_string;
  1102.     }
  1103.     else
  1104.     {
  1105.         name[0] = KEY2TERMCAP0((int)p->bt_entry);
  1106.         name[1] = KEY2TERMCAP1((int)p->bt_entry);
  1107.         if (find_termcode(name) == NULL)
  1108.         add_termcode(name, (char_u *)p->bt_string);
  1109.     }
  1110.     }
  1111. }
  1112.  
  1113. /*
  1114.  * Set terminal options for terminal "term".
  1115.  * Return OK if terminal 'term' was found in a termcap, FAIL otherwise.
  1116.  *
  1117.  * While doing this, until ttest(), some options may be NULL, be careful.
  1118.  */
  1119.     int
  1120. set_termname(term)
  1121.     char_u *term;
  1122. {
  1123.     struct builtin_term *termp;
  1124. #ifdef HAVE_TGETENT
  1125.     int        builtin_first = p_tbi;
  1126.     int        try;
  1127.     int        termcap_cleared = FALSE;
  1128.     static char    nr_colors[15];        /* string for number of colors */
  1129. #endif
  1130.     int        width = 0, height = 0;
  1131.     char_u    *error_msg = NULL;
  1132.     char_u    *bs_p, *del_p;
  1133.  
  1134.     if (term_is_builtin(term))
  1135.     {
  1136.     term += 8;
  1137. #ifdef HAVE_TGETENT
  1138.     builtin_first = 1;
  1139. #endif
  1140.     }
  1141.  
  1142. /*
  1143.  * If HAVE_TGETENT is not defined, only the builtin termcap is used, otherwise:
  1144.  *   If builtin_first is TRUE:
  1145.  *     0. try builtin termcap
  1146.  *     1. try external termcap
  1147.  *     2. if both fail default to a builtin terminal
  1148.  *   If builtin_first is FALSE:
  1149.  *     1. try external termcap
  1150.  *     2. try builtin termcap, if both fail default to a builtin terminal
  1151.  */
  1152. #ifdef HAVE_TGETENT
  1153.     for (try = builtin_first ? 0 : 1; try < 3; ++try)
  1154.     {
  1155.     /*
  1156.      * Use external termcap
  1157.      */
  1158.     if (try == 1)
  1159.     {
  1160.         char_u        *p;
  1161.         static char_u   tstrbuf[TBUFSZ];
  1162.         int            i;
  1163.         char_u        tbuf[TBUFSZ];
  1164.         char_u        *tp;
  1165.         static char        *(key_names[]) =
  1166.                 {
  1167.                 "ku", "kd", "kr",    /* "kl" is a special case */
  1168. # ifdef ARCHIE
  1169.                 "su", "sd",        /* Termcap code made up! */
  1170. # endif
  1171.                 "#4", "%i",
  1172.                 "k1", "k2", "k3", "k4", "k5", "k6",
  1173.                 "k7", "k8", "k9", "k;", "F1", "F2",
  1174.                 "%1", "&8", "kb", "kI", "kD", "kh",
  1175.                 "@7", "kP", "kN", "K1", "K3", "K4", "K5",
  1176.                 NULL
  1177.                 };
  1178.         static struct {
  1179.                 enum SpecialKey dest; /* index in term_strings[] */
  1180.                 char *name;          /* termcap name for string */
  1181.               } string_names[] =
  1182.                 {    {KS_CE, "ce"}, {KS_AL, "al"}, {KS_CAL,"AL"},
  1183.                 {KS_DL, "dl"}, {KS_CDL,"DL"}, {KS_CS, "cs"},
  1184.                 {KS_CL, "cl"}, {KS_CD, "cd"},
  1185.                 {KS_VI, "vi"}, {KS_VE, "ve"}, {KS_MB, "mb"},
  1186.                 {KS_VS, "vs"}, {KS_ME, "me"}, {KS_MR, "mr"},
  1187.                 {KS_MD, "md"}, {KS_SE, "se"}, {KS_SO, "so"},
  1188.                 {KS_CZH,"ZH"}, {KS_CZR,"ZR"}, {KS_UE, "ue"},
  1189.                 {KS_US, "us"}, {KS_CM, "cm"}, {KS_SR, "sr"},
  1190.                 {KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"},
  1191.                 {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"},
  1192.                 {KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"},
  1193.                 {KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_LE, "le"},
  1194.                 {KS_ND, "nd"}, {KS_OP, "op"},
  1195.                 {0, NULL}
  1196.                 };
  1197.  
  1198.         /*
  1199.          * If the external termcap does not have a matching entry, try the
  1200.          * builtin ones.
  1201.          */
  1202.         if ((error_msg = tgetent_error(tbuf, term)) == NULL)
  1203.         {
  1204.         tp = tstrbuf;
  1205.         if (!termcap_cleared)
  1206.         {
  1207.             clear_termoptions();    /* clear old options */
  1208.             termcap_cleared = TRUE;
  1209.         }
  1210.  
  1211.         /* get output strings */
  1212.         for (i = 0; string_names[i].name != NULL; ++i)
  1213.         {
  1214.             if (term_strings[string_names[i].dest] == NULL ||
  1215.                term_strings[string_names[i].dest] == empty_option)
  1216.             term_strings[string_names[i].dest] =
  1217.                        TGETSTR(string_names[i].name, &tp);
  1218.         }
  1219.  
  1220.         if ((T_MS == NULL || T_MS == empty_option) && tgetflag("ms"))
  1221.             T_MS = (char_u *)"y";
  1222.         if ((T_XS == NULL || T_XS == empty_option) && tgetflag("xs"))
  1223.             T_XS = (char_u *)"y";
  1224.         if ((T_DB == NULL || T_DB == empty_option) && tgetflag("db"))
  1225.             T_DB = (char_u *)"y";
  1226.         if ((T_DA == NULL || T_DA == empty_option) && tgetflag("da"))
  1227.             T_DA = (char_u *)"y";
  1228.  
  1229.  
  1230.         /* get key codes */
  1231.  
  1232.         for (i = 0; key_names[i] != NULL; ++i)
  1233.         {
  1234.             if (find_termcode((char_u *)key_names[i]) == NULL)
  1235.             add_termcode((char_u *)key_names[i],
  1236.                           TGETSTR(key_names[i], &tp));
  1237.         }
  1238.  
  1239.             /* if cursor-left == backspace, ignore it (televideo 925) */
  1240.         if (find_termcode((char_u *)"kl") == NULL)
  1241.         {
  1242.             p = TGETSTR("kl", &tp);
  1243.             if (p != NULL && *p != Ctrl('H'))
  1244.             add_termcode((char_u *)"kl", p);
  1245.         }
  1246.  
  1247.         if (height == 0)
  1248.             height = tgetnum("li");
  1249.         if (width == 0)
  1250.             width = tgetnum("co");
  1251.  
  1252.         /*
  1253.          * Get number of colors.  If non-zero, store as string in
  1254.          * nr_colors[].
  1255.          */
  1256.         i = tgetnum("Co");
  1257.         if (i > 0)
  1258.         {
  1259.             sprintf(nr_colors, "%d", i);
  1260.             T_CCO = (char_u *)nr_colors;
  1261.         }
  1262.  
  1263. # ifndef hpux
  1264.         BC = (char *)TGETSTR("bc", &tp);
  1265.         UP = (char *)TGETSTR("up", &tp);
  1266.         p = TGETSTR("pc", &tp);
  1267.         if (p)
  1268.             PC = *p;
  1269. # endif /* hpux */
  1270.         }
  1271.     }
  1272.     else        /* try == 0 || try == 2 */
  1273. #endif /* HAVE_TGETENT */
  1274.     /*
  1275.      * Use builtin termcap
  1276.      */
  1277.     {
  1278. #ifdef HAVE_TGETENT
  1279.         /*
  1280.          * If builtin termcap was already used, there is no need to search
  1281.          * for the builtin termcap again, quit now.
  1282.          */
  1283.         if (try == 2 && builtin_first && termcap_cleared)
  1284.         break;
  1285. #endif
  1286.         /*
  1287.          * search for 'term' in builtin_termcaps[]
  1288.          */
  1289.         termp = find_builtin_term(term);
  1290.         if (termp->bt_string == NULL)    /* did not find it */
  1291.         {
  1292. #ifdef HAVE_TGETENT
  1293.         /*
  1294.          * If try == 0, first try the external termcap. If that is not
  1295.          * found we'll get back here with try == 2.
  1296.          * If termcap_cleared is set we used the external termcap,
  1297.          * don't complain about not finding the term in the builtin
  1298.          * termcap.
  1299.          */
  1300.         if (try == 0)            /* try external one */
  1301.             continue;
  1302.         if (termcap_cleared)        /* found in external termcap */
  1303.             break;
  1304. #endif
  1305.  
  1306.         mch_errmsg("\r\n");
  1307.         if (error_msg != NULL)
  1308.         {
  1309.             mch_errmsg((char *)error_msg);
  1310.             mch_errmsg("\r\n");
  1311.         }
  1312.         mch_errmsg("'");
  1313.         mch_errmsg((char *)term);
  1314.         mch_errmsg("' not known. Available builtin terminals are:\r\n");
  1315.         for (termp = &(builtin_termcaps[0]); termp->bt_string != NULL;
  1316.                                       ++termp)
  1317.         {
  1318.             if (termp->bt_entry == (int)KS_NAME)
  1319.             {
  1320. #ifdef HAVE_TGETENT
  1321.             mch_errmsg("    builtin_");
  1322. #else
  1323.             mch_errmsg("    ");
  1324. #endif
  1325.             mch_errmsg(termp->bt_string);
  1326.             mch_errmsg("\r\n");
  1327.             }
  1328.         }
  1329.         if (!starting)    /* when user typed :set term=xxx, quit here */
  1330.         {
  1331.             screen_start();    /* don't know where cursor is now */
  1332.             wait_return(TRUE);
  1333.             return FAIL;
  1334.         }
  1335.         term = DEFAULT_TERM;
  1336.         mch_errmsg("defaulting to '");
  1337.         mch_errmsg((char *)term);
  1338.         mch_errmsg("'\r\n");
  1339.         screen_start();        /* don't know where cursor is now */
  1340.         ui_delay(2000L, TRUE);
  1341.         set_string_option_direct((char_u *)"term", -1, term, TRUE);
  1342.         mch_display_error();
  1343.         }
  1344.         out_flush();
  1345. #ifdef HAVE_TGETENT
  1346.         if (!termcap_cleared)
  1347.         {
  1348. #endif
  1349.         clear_termoptions();        /* clear old options */
  1350. #ifdef HAVE_TGETENT
  1351.         termcap_cleared = TRUE;
  1352.         }
  1353. #endif
  1354.         parse_builtin_tcap(term);
  1355. #ifdef USE_GUI
  1356.         if (term_is_gui(term))
  1357.         {
  1358.         out_flush();
  1359.         gui_init();
  1360. #ifdef HAVE_TGETENT
  1361.         break;        /* don't try using external termcap */
  1362. #endif
  1363.         }
  1364. #endif /* USE_GUI */
  1365.     }
  1366. #ifdef HAVE_TGETENT
  1367.     }
  1368. #endif
  1369.  
  1370. /*
  1371.  * special: There is no info in the termcap about whether the cursor
  1372.  * positioning is relative to the start of the screen or to the start of the
  1373.  * scrolling region.  We just guess here. Only msdos pcterm is known to do it
  1374.  * relative.
  1375.  */
  1376.     if (STRCMP(term, "pcterm") == 0)
  1377.     T_CCS = (char_u *)"yes";
  1378.     else
  1379.     T_CCS = empty_option;
  1380.  
  1381. #ifdef UNIX
  1382. /*
  1383.  * Any "stty" settings override the default for t_kb from the termcap.
  1384.  * This is in os_unix.c, because it depends a lot on the version of unix that
  1385.  * is being used.
  1386.  * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly.
  1387.  */
  1388. #ifdef USE_GUI
  1389.     if (!gui.in_use)
  1390. #endif
  1391.     get_stty();
  1392. #endif
  1393.  
  1394. /*
  1395.  * If the termcap has no entry for 'bs' and/or 'del' and the ioctl() also
  1396.  * didn't work, use the default CTRL-H
  1397.  * The default for t_kD is DEL, unless t_kb is DEL.
  1398.  * The vim_strsave'd strings are probably lost forever, well it's only two
  1399.  * bytes.  Don't do this when the GUI is active, it uses "t_kb" and "t_kD"
  1400.  * directly.
  1401.  */
  1402. #ifdef USE_GUI
  1403.     if (!gui.in_use)
  1404. #endif
  1405.     {
  1406.     bs_p = find_termcode((char_u *)"kb");
  1407.     del_p = find_termcode((char_u *)"kD");
  1408.     if (bs_p == NULL || *bs_p == NUL)
  1409.         add_termcode((char_u *)"kb", (bs_p = (char_u *)"\010"));
  1410.     if ((del_p == NULL || *del_p == NUL) &&
  1411.                         (bs_p == NULL || *bs_p != '\177'))
  1412.         add_termcode((char_u *)"kD", (char_u *)"\177");
  1413.     }
  1414.  
  1415. #ifdef USE_MOUSE
  1416.     /*
  1417.      * Recognize mouse events in the input stream for xterm, msdos and win32.
  1418.      * Also for Netterm and Dec mouse, when defined at compile time.
  1419.      */
  1420.     {
  1421.     char_u    name[2];
  1422.  
  1423.     name[0] = (int)KS_MOUSE;
  1424.     name[1] = K_FILLER;
  1425. # ifdef UNIX
  1426. #  ifdef XTERM_MOUSE
  1427.     if (vim_is_xterm(term))
  1428.         add_termcode(name, (char_u *)"\033[M");
  1429. #  endif
  1430. #  ifdef NETTERM_MOUSE
  1431.     name[0] = (int)KS_NETTERM_MOUSE;
  1432.     add_termcode(name, (char_u *)"\033}");
  1433. #  endif
  1434. #  ifdef DEC_MOUSE
  1435.     if (!vim_is_xterm(term))    /* conflicts with xterm mouse: "\033[" and "\033[M" */
  1436.     {
  1437.         name[0] = (int)KS_DEC_MOUSE;
  1438.         add_termcode(name, (char_u *)"\033[");
  1439.     }
  1440. #  endif
  1441. # else    /* UNIX */
  1442.     add_termcode(name, (char_u *)"\233M");
  1443. # endif    /* UNIX */
  1444.     }
  1445. #endif    /* USE_MOUSE */
  1446.  
  1447. #ifdef USE_SNIFF
  1448.     {
  1449.     char_u    name[2];
  1450.  
  1451.     name[0] = (int)KS_EXTRA;
  1452.     name[1] = (int)KE_SNIFF;
  1453.     add_termcode(name, (char_u *)"\233sniff");
  1454.     }
  1455. #endif
  1456.  
  1457. #if defined(AMIGA) || defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(__BEOS__)
  1458.     /* DEFAULT_TERM indicates that it is the machine console. */
  1459.     if (STRCMP(term, DEFAULT_TERM))
  1460.     term_console = FALSE;
  1461.     else
  1462.     {
  1463.     term_console = TRUE;
  1464. # ifdef AMIGA
  1465.     win_resize_on();    /* enable window resizing reports */
  1466. # endif
  1467.     }
  1468. #endif
  1469.  
  1470. #ifdef UNIX
  1471. /*
  1472.  * 'ttyfast' is default on for xterm, iris-ansi and a few others.
  1473.  */
  1474.     if (vim_is_fastterm(term))
  1475.     p_tf = TRUE;
  1476. #endif
  1477. #if defined(AMIGA) || defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(__BEOS__)
  1478. /*
  1479.  * 'ttyfast' is default on Amiga, MSDOS, Win32, BeBox and OS/2 consoles
  1480.  */
  1481.     if (term_console)
  1482.     p_tf = TRUE;
  1483. #endif
  1484.  
  1485.     ttest(TRUE);    /* make sure we have a valid set of terminal codes */
  1486.  
  1487.     full_screen = TRUE;        /* we can use termcap codes from now on */
  1488.     set_term_defaults();    /* use current values as defaults */
  1489.  
  1490.     /*
  1491.      * Initialize the terminal with the appropriate termcap codes.
  1492.      * Set the mouse and window title if possible.
  1493.      * Don't do this when starting, need to parse the .vimrc first, because it
  1494.      * may redefine t_TI etc.
  1495.      */
  1496.     if (!starting)
  1497.     {
  1498.     starttermcap();        /* may change terminal mode */
  1499. #ifdef USE_MOUSE
  1500.     setmouse();        /* may start using the mouse */
  1501. #endif
  1502.     maketitle();        /* may display window title */
  1503.     }
  1504.  
  1505.     /* display initial screen after ttest() checking. jw. */
  1506.     if (width <= 0 || height <= 0)
  1507.     {
  1508.     /* termcap failed to report size */
  1509.     /* set defaults, in case ui_get_winsize also fails */
  1510.     width = 80;
  1511. #if defined MSDOS  ||  defined WIN32
  1512.     height = 25;        /* console is often 25 lines */
  1513. #else
  1514.     height = 24;        /* most terminals are 24 lines */
  1515. #endif
  1516.     }
  1517.     set_winsize(width, height, FALSE);    /* may change Rows */
  1518.     if (!starting)
  1519.     {
  1520.     if (scroll_region)
  1521.         scroll_region_reset();        /* In case Rows changed */
  1522.     check_map_keycodes();    /* check mappings for terminal codes used */
  1523.  
  1524. #ifdef AUTOCMD
  1525.     {
  1526.         BUF        *old_curbuf;
  1527.  
  1528.         /*
  1529.          * Execute the TermChanged autocommands for each buffer that is
  1530.          * loaded.
  1531.          */
  1532.         old_curbuf = curbuf;
  1533.         for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next)
  1534.         {
  1535.         if (curbuf->b_ml.ml_mfp != NULL)
  1536.             apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE);
  1537.         }
  1538.         if (buf_valid(old_curbuf))
  1539.         curbuf = old_curbuf;
  1540.     }
  1541. #endif
  1542.     }
  1543.  
  1544.     return OK;
  1545. }
  1546.  
  1547. #ifdef HAVE_TGETENT
  1548. /*
  1549.  * Call tgetent()
  1550.  * Return error message if it fails, NULL if it's OK.
  1551.  */
  1552.     static char_u *
  1553. tgetent_error(tbuf, term)
  1554.     char_u  *tbuf;
  1555.     char_u  *term;
  1556. {
  1557.     int        i;
  1558.  
  1559.     i = TGETENT(tbuf, term);
  1560.     if (i == -1)
  1561.     return (char_u *)"Cannot open termcap file";
  1562.     if (i == 0)
  1563. #ifdef TERMINFO
  1564.     return (char_u *)"Terminal entry not found in terminfo";
  1565. #else
  1566.     return (char_u *)"Terminal entry not found in termcap";
  1567. #endif
  1568.     return NULL;
  1569. }
  1570. #endif /* HAVE_TGETENT */
  1571.  
  1572. #if defined(HAVE_TGETENT) && (defined(UNIX) || defined(__EMX__))
  1573. /*
  1574.  * Get Columns and Rows from the termcap. Used after a window signal if the
  1575.  * ioctl() fails. It doesn't make sense to call tgetent each time if the "co"
  1576.  * and "li" entries never change. But on some systems this works.
  1577.  * Errors while getting the entries are ignored.
  1578.  */
  1579.     void
  1580. getlinecol()
  1581. {
  1582.     char_u        tbuf[TBUFSZ];
  1583.  
  1584.     if (T_NAME != NULL && *T_NAME != NUL && TGETENT(tbuf, T_NAME) > 0)
  1585.     {
  1586.     if (Columns == 0)
  1587.         Columns = tgetnum("co");
  1588.     if (Rows == 0)
  1589.         Rows = tgetnum("li");
  1590.     }
  1591. }
  1592. #endif /* defined(HAVE_TGETENT) && defined(UNIX) */
  1593.  
  1594. /*
  1595.  * Get a string entry from the termcap and add it to the list of termcodes.
  1596.  * Used for <t_xx> special keys.
  1597.  * Give an error message for failure when not sourcing.
  1598.  * If force given, replace an existing entry.
  1599.  * Return FAIL if the entry was not found, OK if the entry was added.
  1600.  */
  1601.     int
  1602. add_termcap_entry(name, force)
  1603.     char_u  *name;
  1604.     int        force;
  1605. {
  1606.     char_u  *term;
  1607.     int        key;
  1608.     struct builtin_term *termp;
  1609. #ifdef HAVE_TGETENT
  1610.     char_u  *string;
  1611.     int        i;
  1612.     int        builtin_first;
  1613.     char_u  tbuf[TBUFSZ];
  1614.     char_u  tstrbuf[TBUFSZ];
  1615.     char_u  *tp = tstrbuf;
  1616.     char_u  *error_msg = NULL;
  1617. #endif
  1618.  
  1619. /*
  1620.  * If the GUI is running or will start in a moment, we only support the keys
  1621.  * that the GUI can produce.
  1622.  */
  1623. #ifdef USE_GUI
  1624.     if (gui.in_use || gui.starting)
  1625.     return gui_mch_haskey(name);
  1626. #endif
  1627.  
  1628.     if (!force && find_termcode(name) != NULL)        /* it's already there */
  1629.     return OK;
  1630.  
  1631.     term = T_NAME;
  1632.     if (term == NULL || *term == NUL)        /* 'term' not defined yet */
  1633.     return FAIL;
  1634.  
  1635.     if (term_is_builtin(term))            /* name starts with "builtin_" */
  1636.     {
  1637.     term += 8;
  1638. #ifdef HAVE_TGETENT
  1639.     builtin_first = TRUE;
  1640. #endif
  1641.     }
  1642. #ifdef HAVE_TGETENT
  1643.     else
  1644.     builtin_first = p_tbi;
  1645. #endif
  1646.  
  1647. #ifdef HAVE_TGETENT
  1648. /*
  1649.  * We can get the entry from the builtin termcap and from the external one.
  1650.  * If 'ttybuiltin' is on or the terminal name starts with "builtin_", try
  1651.  * builtin termcap first.
  1652.  * If 'ttybuiltin' is off, try external termcap first.
  1653.  */
  1654.     for (i = 0; i < 2; ++i)
  1655.     {
  1656.     if (!builtin_first == i)
  1657. #endif
  1658.     /*
  1659.      * Search in builtin termcap
  1660.      */
  1661.     {
  1662.         termp = find_builtin_term(term);
  1663.         if (termp->bt_string != NULL)    /* found it */
  1664.         {
  1665.         key = TERMCAP2KEY(name[0], name[1]);
  1666.         while (termp->bt_entry != (int)KS_NAME)
  1667.         {
  1668.             if ((int)termp->bt_entry == key)
  1669.             {
  1670.             add_termcode(name, (char_u *)termp->bt_string);
  1671.             return OK;
  1672.             }
  1673.             ++termp;
  1674.         }
  1675.         }
  1676.     }
  1677. #ifdef HAVE_TGETENT
  1678.     else
  1679.     /*
  1680.      * Search in external termcap
  1681.      */
  1682.     {
  1683.         error_msg = tgetent_error(tbuf, term);
  1684.         if (error_msg == NULL)
  1685.         {
  1686.         string = TGETSTR((char *)name, &tp);
  1687.         if (string != NULL && *string != NUL)
  1688.         {
  1689.             add_termcode(name, string);
  1690.             return OK;
  1691.         }
  1692.         }
  1693.     }
  1694.     }
  1695. #endif
  1696.  
  1697.     if (sourcing_name == NULL)
  1698.     {
  1699. #ifdef HAVE_TGETENT
  1700.     if (error_msg != NULL)
  1701.         EMSG(error_msg);
  1702.     else
  1703. #endif
  1704.         EMSG2("No \"%s\" entry in termcap", name);
  1705.     }
  1706.     return FAIL;
  1707. }
  1708.  
  1709.     static int
  1710. term_is_builtin(name)
  1711.     char_u  *name;
  1712. {
  1713.     return (STRNCMP(name, "builtin_", (size_t)8) == 0);
  1714. }
  1715.  
  1716. #ifdef USE_GUI
  1717.     int
  1718. term_is_gui(name)
  1719.     char_u  *name;
  1720. {
  1721.     return (STRCMP(name, "builtin_gui") == 0 || STRCMP(name, "gui") == 0);
  1722. }
  1723. #endif
  1724.  
  1725. #if !defined(HAVE_TGETENT) || defined(AMIGA) || defined(PROTO)
  1726.  
  1727.     char_u *
  1728. tltoa(i)
  1729.     unsigned long i;
  1730. {
  1731.     static char_u buf[16];
  1732.     char_u    *p;
  1733.  
  1734.     p = buf + 15;
  1735.     *p = '\0';
  1736.     do
  1737.     {
  1738.     --p;
  1739.     *p = (char_u) (i % 10 + '0');
  1740.     i /= 10;
  1741.     }
  1742.     while (i > 0 && p > buf);
  1743.     return p;
  1744. }
  1745. #endif
  1746.  
  1747. #ifndef HAVE_TGETENT
  1748.  
  1749. /*
  1750.  * minimal tgoto() implementation.
  1751.  * no padding and we only parse for %i %d and %+char
  1752.  */
  1753. char *tgoto __ARGS((char *, int, int));
  1754.  
  1755.     char *
  1756. tgoto(cm, x, y)
  1757.     char *cm;
  1758.     int x, y;
  1759. {
  1760.     static char buf[30];
  1761.     char *p, *s, *e;
  1762.  
  1763.     if (!cm)
  1764.     return "OOPS";
  1765.     e = buf + 29;
  1766.     for (s = buf; s < e && *cm; cm++)
  1767.     {
  1768.     if (*cm != '%')
  1769.     {
  1770.         *s++ = *cm;
  1771.         continue;
  1772.     }
  1773.     switch (*++cm)
  1774.     {
  1775.     case 'd':
  1776.         p = (char *)tltoa((unsigned long)y);
  1777.         y = x;
  1778.         while (*p)
  1779.         *s++ = *p++;
  1780.         break;
  1781.     case 'i':
  1782.         x++;
  1783.         y++;
  1784.         break;
  1785.     case '+':
  1786.         *s++ = (char)(*++cm + y);
  1787.         y = x;
  1788.         break;
  1789.     case '%':
  1790.         *s++ = *cm;
  1791.         break;
  1792.     default:
  1793.         return "OOPS";
  1794.     }
  1795.     }
  1796.     *s = '\0';
  1797.     return buf;
  1798. }
  1799.  
  1800. #endif /* HAVE_TGETENT */
  1801.  
  1802. /*
  1803.  * Set the terminal name and initialize the terminal options.
  1804.  * If "name" is NULL or empty, get the terminal name from the environment.
  1805.  * If that fails, use the default terminal name.
  1806.  */
  1807.     void
  1808. termcapinit(name)
  1809.     char_u *name;
  1810. {
  1811.     char_u    *term;
  1812.  
  1813.     if (name != NULL && *name == NUL)
  1814.     name = NULL;        /* empty name is equal to no name */
  1815.     term = name;
  1816.  
  1817. #ifdef __BEOS__
  1818.     /*
  1819.      * TERM environment variable is normally set to 'ansi' on the Bebox;
  1820.      * Since the BeBox doesn't quite support full ANSI yet, we use our
  1821.      * own custom 'ansi-beos' termcap instead, unless the -T option has
  1822.      * been given on the command line.
  1823.      */
  1824.     if (term == NULL
  1825.          && strcmp((char *)vim_getenv((char_u *)"TERM"), "ansi") == 0)
  1826.     term = DEFAULT_TERM;
  1827. #endif
  1828. #ifndef WIN32
  1829.     if (term == NULL)
  1830.     term = vim_getenv((char_u *)"TERM");
  1831. #endif
  1832.     if (term == NULL || *term == NUL)
  1833.     term = DEFAULT_TERM;
  1834.     set_string_option_direct((char_u *)"term", -1, term, TRUE);
  1835.  
  1836.     /* Set the default terminal name. */
  1837.     set_string_default("term", term);
  1838.     set_string_default("ttytype", term);
  1839.  
  1840.     /*
  1841.      * Avoid using "term" here, because the next vim_getenv() may overwrite it.
  1842.      */
  1843.     set_termname(T_NAME != NULL ? T_NAME : term);
  1844. }
  1845.  
  1846. /*
  1847.  * the number of calls to ui_write is reduced by using the buffer "out_buf"
  1848.  */
  1849. #ifdef DOS16
  1850. # define OUT_SIZE    255        /* only have 640K total... */
  1851. #else
  1852. # define OUT_SIZE    2047
  1853. #endif
  1854.         /* Add one to allow mch_write() in os_win32.c to append a NUL */
  1855. static char_u        out_buf[OUT_SIZE + 1];
  1856. static int        out_pos = 0;    /* number of chars in out_buf */
  1857.  
  1858. /*
  1859.  * out_flush(): flush the output buffer
  1860.  */
  1861.     void
  1862. out_flush()
  1863. {
  1864.     int        len;
  1865.  
  1866.     if (out_pos != 0)
  1867.     {
  1868.     /* set out_pos to 0 before ui_write, to avoid recursiveness */
  1869.     len = out_pos;
  1870.     out_pos = 0;
  1871.     ui_write(out_buf, len);
  1872.     }
  1873. }
  1874.  
  1875. #ifdef USE_GUI
  1876. /*
  1877.  * out_trash(): Throw away the contents of the output buffer
  1878.  */
  1879.     void
  1880. out_trash()
  1881. {
  1882.     out_pos = 0;
  1883. }
  1884. #endif
  1885.  
  1886. /*
  1887.  * out_char(c): put a character into the output buffer.
  1888.  *        Flush it if it becomes full.
  1889.  * This should not be used for outputting text on the screen (use functions
  1890.  * like msg_puts() and screen_putchar() for that).
  1891.  */
  1892.     void
  1893. out_char(c)
  1894.     unsigned    c;
  1895. {
  1896. #if defined(UNIX) || defined(VMS) || defined(AMIGA)
  1897.     if (c == '\n')    /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
  1898.     out_char('\r');
  1899. #endif
  1900.  
  1901.     out_buf[out_pos++] = c;
  1902.  
  1903.     /* For testing we flush each time. */
  1904.     if (out_pos >= OUT_SIZE || p_wd)
  1905.     out_flush();
  1906. }
  1907.  
  1908. static void out_char_nf __ARGS((unsigned));
  1909.  
  1910. /*
  1911.  * out_char_nf(c): like out_char(), but don't flush when p_wd is set
  1912.  */
  1913.     static void
  1914. out_char_nf(c)
  1915.     unsigned    c;
  1916. {
  1917. #if defined(UNIX) || defined(VMS) || defined(AMIGA)
  1918.     if (c == '\n')    /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
  1919.     out_char_nf('\r');
  1920. #endif
  1921.  
  1922.     out_buf[out_pos++] = c;
  1923.  
  1924.     if (out_pos >= OUT_SIZE)
  1925.     out_flush();
  1926. }
  1927.  
  1928. /*
  1929.  * A never-padding out_str.
  1930.  * use this whenever you don't want to run the string through tputs.
  1931.  * tputs above is harmless, but tputs from the termcap library
  1932.  * is likely to strip off leading digits, that it mistakes for padding
  1933.  * information. (jw)
  1934.  * This should only be used for writing terminal codes, not for outputting
  1935.  * normal text (use functions like msg_puts() and screen_putchar() for that).
  1936.  */
  1937.     void
  1938. out_str_nf(s)
  1939.     char_u *s;
  1940. {
  1941.     if (out_pos > OUT_SIZE - 20)  /* avoid terminal strings being split up */
  1942.     out_flush();
  1943.     while (*s)
  1944.     out_char_nf(*s++);
  1945.  
  1946.     /* For testing we write one string at a time. */
  1947.     if (p_wd)
  1948.     out_flush();
  1949. }
  1950.  
  1951. /*
  1952.  * out_str(s): Put a string character at a time into the output buffer.
  1953.  * If HAVE_TGETENT is defined use the termcap parser. (jw)
  1954.  * This should only be used for writing terminal codes, not for outputting
  1955.  * normal text (use functions like msg_puts() and screen_putchar() for that).
  1956.  */
  1957.     void
  1958. out_str(s)
  1959.     char_u     *s;
  1960. {
  1961.     if (out_pos > OUT_SIZE - 20)  /* avoid terminal strings being split up */
  1962.     out_flush();
  1963.     if (s != NULL && *s)
  1964. #ifdef HAVE_TGETENT
  1965.     tputs((char *)s, 1, TPUTSFUNCAST out_char_nf);
  1966. #else
  1967.     while (*s)
  1968.         out_char_nf(*s++);
  1969. #endif
  1970.  
  1971.     /* For testing we write one string at a time. */
  1972.     if (p_wd)
  1973.     out_flush();
  1974. }
  1975.  
  1976. /*
  1977.  * cursor positioning using termcap parser. (jw)
  1978.  */
  1979.     void
  1980. term_windgoto(row, col)
  1981.     int        row;
  1982.     int        col;
  1983. {
  1984.     OUT_STR(tgoto((char *)T_CM, col, row));
  1985. }
  1986.  
  1987.     void
  1988. term_cursor_right(i)
  1989.     int        i;
  1990. {
  1991.     OUT_STR(tgoto((char *)T_CRI, 0, i));
  1992. }
  1993.  
  1994.     void
  1995. term_append_lines(line_count)
  1996.     int        line_count;
  1997. {
  1998.     OUT_STR(tgoto((char *)T_CAL, 0, line_count));
  1999. }
  2000.  
  2001.     void
  2002. term_delete_lines(line_count)
  2003.     int        line_count;
  2004. {
  2005.     OUT_STR(tgoto((char *)T_CDL, 0, line_count));
  2006. }
  2007.  
  2008.     void
  2009. term_fg_color(n)
  2010.     int        n;
  2011. {
  2012.     /* Use "AF" termcap entry if present, "Sf" entry otherwise */
  2013.     if (*T_CAF)
  2014.     term_color(T_CAF, n);
  2015.     else if (*T_CSF)
  2016.     term_color(T_CSF, n);
  2017. }
  2018.  
  2019.     void
  2020. term_bg_color(n)
  2021.     int        n;
  2022. {
  2023.     /* Use "AB" termcap entry if present, "Sb" entry otherwise */
  2024.     if (*T_CAB)
  2025.     term_color(T_CAB, n);
  2026.     else if (*T_CSB)
  2027.     term_color(T_CSB, n);
  2028. }
  2029.  
  2030.     static void
  2031. term_color(s, n)
  2032.     char_u  *s;
  2033.     int        n;
  2034. {
  2035.     /* Special handling of 16 colors, because termcap can't handle it */
  2036.     if (n > 7 && atoi((char *)T_CCO) == 16
  2037.           && s[0] == ESC && s[1] == '[' && s[2] != NUL
  2038. #ifdef TERMINFO
  2039.           && STRCMP(s + 3, "%p1%dm") == 0
  2040. #else
  2041.           && STRCMP(s + 3, "%dm") == 0
  2042. #endif
  2043.         )
  2044.     {
  2045.     if (s[2] == '3')    /* foreground */
  2046.     {
  2047. #ifdef TERMINFO
  2048.         OUT_STR(tgoto("\033[9%p1%dm", 0, n - 8));
  2049. #else
  2050.         OUT_STR(tgoto("\033[9%dm", 0, n - 8));
  2051. #endif
  2052.         return;
  2053.     }
  2054.     if (s[2] == '4')    /* background */
  2055.     {
  2056. #ifdef TERMINFO
  2057.         OUT_STR(tgoto("\033[10%p1%dm", 0, n - 8));
  2058. #else
  2059.         OUT_STR(tgoto("\033[10%dm", 0, n - 8));
  2060. #endif
  2061.         return;
  2062.     }
  2063.  
  2064.     }
  2065.     OUT_STR(tgoto((char *)s, 0, n));
  2066. }
  2067.  
  2068. /*
  2069.  * Make sure we have a valid set or terminal options.
  2070.  * Replace all entries that are NULL by empty_option
  2071.  */
  2072.     void
  2073. ttest(pairs)
  2074.     int    pairs;
  2075. {
  2076.     char    *t = NULL;
  2077.  
  2078.     check_options();            /* make sure no options are NULL */
  2079.  
  2080.   /* hard requirements */
  2081.     if (*T_CL == NUL)            /* erase display */
  2082.     t = "cl";
  2083.     if (*T_CM == NUL)            /* cursor motion */
  2084.     t = "cm";
  2085.  
  2086.     if (t != NULL)
  2087.     EMSG2("terminal capability %s required", t);
  2088.  
  2089. /*
  2090.  * if "cs" defined, use a scroll region, it's faster.
  2091.  */
  2092.     if (*T_CS != NUL)
  2093.     scroll_region = TRUE;
  2094.     else
  2095.     scroll_region = FALSE;
  2096.  
  2097.     if (pairs)
  2098.     {
  2099.     /*
  2100.      * optional pairs
  2101.      */
  2102.     /* TP goes to normal mode for TI (invert) and TB (bold) */
  2103.     if (*T_ME == NUL)
  2104.         T_ME = T_MR = T_MD = T_MB = empty_option;
  2105.     if (*T_SO == NUL || *T_SE == NUL)
  2106.         T_SO = T_SE = empty_option;
  2107.     if (*T_US == NUL || *T_UE == NUL)
  2108.         T_US = T_UE = empty_option;
  2109.     if (*T_CZH == NUL || *T_CZR == NUL)
  2110.         T_CZH = T_CZR = empty_option;
  2111.  
  2112.     /* T_VE is needed even though T_VI is not defined */
  2113.     if (*T_VE == NUL)
  2114.         T_VI = empty_option;
  2115.  
  2116.     /* if 'mr' or 'me' is not defined use 'so' and 'se' */
  2117.     if (*T_ME == NUL)
  2118.     {
  2119.         T_ME = T_SE;
  2120.         T_MR = T_SO;
  2121.         T_MD = T_SO;
  2122.     }
  2123.  
  2124.     /* if 'so' or 'se' is not defined use 'mr' and 'me' */
  2125.     if (*T_SO == NUL)
  2126.     {
  2127.         T_SE = T_ME;
  2128.         if (*T_MR == NUL)
  2129.         T_SO = T_MD;
  2130.         else
  2131.         T_SO = T_MR;
  2132.     }
  2133.  
  2134.     /* if 'ZH' or 'ZR' is not defined use 'mr' and 'me' */
  2135.     if (*T_CZH == NUL)
  2136.     {
  2137.         T_CZR = T_ME;
  2138.         if (*T_MR == NUL)
  2139.         T_CZH = T_MD;
  2140.         else
  2141.         T_CZH = T_MR;
  2142.     }
  2143.  
  2144.     /* "Sb" and "Sf" come in pairs */
  2145.     if (*T_CSB == NUL || *T_CSF == NUL)
  2146.     {
  2147.         T_CSB = empty_option;
  2148.         T_CSF = empty_option;
  2149.     }
  2150.  
  2151.     /* "AB" and "AF" come in pairs */
  2152.     if (*T_CAB == NUL || *T_CAF == NUL)
  2153.     {
  2154.         T_CAB = empty_option;
  2155.         T_CAF = empty_option;
  2156.     }
  2157.  
  2158.     /* if 'Sb' and 'AB' are not defined, reset "Co" */
  2159.     if (*T_CSB == NUL && *T_CAB == NUL)
  2160.         T_CCO = empty_option;
  2161.  
  2162.     /* Set 'weirdinvert' according to value of 't_xs' */
  2163.     p_wiv = (*T_XS != NUL);
  2164.     }
  2165.     need_gather = TRUE;
  2166. }
  2167.  
  2168. /*
  2169.  * Represent the given long_u as individual bytes, with the most significant
  2170.  * byte first, and store them in dst.
  2171.  */
  2172.     void
  2173. add_long_to_buf(val, dst)
  2174.     long_u  val;
  2175.     char_u  *dst;
  2176. {
  2177.     int        i;
  2178.     int        shift;
  2179.  
  2180.     for (i = 1; i <= sizeof(long_u); i++)
  2181.     {
  2182.     shift = 8 * (sizeof(long_u) - i);
  2183.     dst[i - 1] = (char_u) ((val >> shift) & 0xff);
  2184.     }
  2185. }
  2186.  
  2187. /*
  2188.  * Interpret the next string of bytes in buf as a long integer, with the most
  2189.  * significant byte first.  Note that it is assumed that buf has been through
  2190.  * inchar(), so that NUL and K_SPECIAL will be represented as three bytes each.
  2191.  * Puts result in val, and returns the number of bytes read from buf
  2192.  * (between sizeof(long_u) and 2 * sizeof(long_u)), or -1 if not enough bytes
  2193.  * were present.
  2194.  */
  2195.     int
  2196. get_long_from_buf(buf, val)
  2197.     char_u  *buf;
  2198.     long_u  *val;
  2199. {
  2200.     int        len;
  2201.     char_u  bytes[sizeof(long_u)];
  2202.     int        i;
  2203.     int        shift;
  2204.  
  2205.     *val = 0;
  2206.     len = get_bytes_from_buf(buf, bytes, (int)sizeof(long_u));
  2207.     if (len != -1)
  2208.     {
  2209.     for (i = 0; i < sizeof(long_u); i++)
  2210.     {
  2211.         shift = 8 * (sizeof(long_u) - 1 - i);
  2212.         *val += (long_u)bytes[i] << shift;
  2213.     }
  2214.     }
  2215.     return len;
  2216. }
  2217.  
  2218. /*
  2219.  * Read the next num_bytes bytes from buf, and store them in bytes.  Assume
  2220.  * that buf has been through inchar().    Returns the actual number of bytes used
  2221.  * from buf (between num_bytes and num_bytes*2), or -1 if not enough bytes were
  2222.  * available.
  2223.  */
  2224.     static int
  2225. get_bytes_from_buf(buf, bytes, num_bytes)
  2226.     char_u  *buf;
  2227.     char_u  *bytes;
  2228.     int        num_bytes;
  2229. {
  2230.     int        len = 0;
  2231.     int        i;
  2232.     char_u  c;
  2233.  
  2234.     for (i = 0; i < num_bytes; i++)
  2235.     {
  2236.     if ((c = buf[len++]) == NUL)
  2237.         return -1;
  2238.     if (c == K_SPECIAL)
  2239.     {
  2240.         if (buf[len] == NUL || buf[len + 1] == NUL)        /* cannot happen? */
  2241.         return -1;
  2242.         if (buf[len++] == (int)KS_ZERO)
  2243.         c = NUL;
  2244.         ++len;    /* skip K_FILLER */
  2245.         /* else it should be KS_SPECIAL, and c already equals K_SPECIAL */
  2246.     }
  2247.     bytes[i] = c;
  2248.     }
  2249.     return len;
  2250. }
  2251.  
  2252.     void
  2253. check_winsize()
  2254. {
  2255.     static int    old_Rows = 0;
  2256.  
  2257.     if (Columns < MIN_COLUMNS)
  2258.     Columns = MIN_COLUMNS;
  2259.     if (Rows < min_rows())    /* need room for one window and command line */
  2260.     Rows = min_rows();
  2261.  
  2262.     if (old_Rows != Rows)
  2263.     {
  2264.     old_Rows = Rows;
  2265.     screen_new_rows();        /* may need to update window sizes */
  2266.     }
  2267. }
  2268.  
  2269. /*
  2270.  * set window size
  2271.  * If 'mustset' is TRUE, we must set Rows and Columns, do not get real
  2272.  * window size (this is used for the :win command).
  2273.  * If 'mustset' is FALSE, we may try to get the real window size and if
  2274.  * it fails use 'width' and 'height'.
  2275.  */
  2276.     void
  2277. set_winsize(width, height, mustset)
  2278.     int        width, height;
  2279.     int        mustset;
  2280. {
  2281.     static int        busy = FALSE;
  2282.  
  2283.     /*
  2284.      * Avoid recursiveness, can happen when setting the window size causes
  2285.      * another window-changed signal.
  2286.      */
  2287.     if (busy)
  2288.     return;
  2289.  
  2290.     if (width < 0 || height < 0)    /* just checking... */
  2291.     return;
  2292.  
  2293.     if (State == HITRETURN || State == SETWSIZE) /* postpone the resizing */
  2294.     {
  2295.     State = SETWSIZE;
  2296.     return;
  2297.     }
  2298.  
  2299.     ++busy;
  2300.  
  2301.     if (State != ASKMORE && State != EXTERNCMD)
  2302.     screenclear();
  2303.     else
  2304.     screen_start();        /* don't know where cursor is now */
  2305. #ifdef AMIGA
  2306.     out_flush();        /* must do this before mch_get_winsize() for some
  2307.                    obscure reason */
  2308. #endif /* AMIGA */
  2309.  
  2310.     if (mustset || (ui_get_winsize() == FAIL && height != 0))
  2311.     {
  2312.     Rows = height;
  2313.     Columns = width;
  2314.     check_winsize();    /* always check, to get p_scroll right */
  2315.     ui_set_winsize();
  2316.     }
  2317.     else
  2318.     check_winsize();    /* always check, to get p_scroll right */
  2319.  
  2320.     if (!starting)
  2321.     {
  2322.     maketitle();
  2323.  
  2324.     /*
  2325.      * We only redraw when it's needed:
  2326.      * - While at the more prompt or executing an external command, don't
  2327.      *   redraw, but position the cursor.
  2328.      * - While editing the command line, only redraw that.
  2329.      * - in Ex mode, don't redraw anything.
  2330.      * - Otherwise, redraw right now, and position the cursor.
  2331.      * Always need to call update_screen() or screenalloc(), to make
  2332.      * sure Rows/Columns and the size of NextScreen is correct!
  2333.      */
  2334.     if (State == ASKMORE || State == EXTERNCMD)
  2335.     {
  2336.         screenalloc(FALSE);
  2337.         if (State == ASKMORE)
  2338.         {
  2339.         msg_moremsg(FALSE); /* display --more-- message again */
  2340.         msg_row = Rows - 1;
  2341.         }
  2342.         else
  2343.         windgoto(msg_row, msg_col); /* put cursor back */
  2344.     }
  2345.     else if (State == CMDLINE)
  2346.     {
  2347.         update_screen(NOT_VALID);
  2348.         redrawcmdline();
  2349.     }
  2350.     else if (exmode_active)
  2351.     {
  2352.         screenalloc(FALSE);
  2353.     }
  2354.     else
  2355.     {
  2356.         update_topline();
  2357.         update_screen(NOT_VALID);
  2358.         if (redrawing())
  2359.         setcursor();
  2360.     }
  2361.     cursor_on();        /* redrawing may have switched it off */
  2362.     }
  2363.     out_flush();
  2364.     --busy;
  2365. }
  2366.  
  2367. /*
  2368.  * Set the terminal to TMODE_RAW (for Normal mode) or TMODE_COOK (for external
  2369.  * commands and Ex mode).
  2370.  */
  2371.     void
  2372. settmode(tmode)
  2373.     int     tmode;
  2374. {
  2375.     static int    oldtmode = TMODE_COOK;
  2376.  
  2377. #ifdef USE_GUI
  2378.     /* don't set the term where gvim was started to any mode */
  2379.     if (gui.in_use)
  2380.     return;
  2381. #endif
  2382.  
  2383.     if (full_screen)
  2384.     {
  2385.     /*
  2386.      * When returning after calling a shell we want to really set the
  2387.      * terminal to raw mode, even though we think it already is, because
  2388.      * the shell program may have reset the terminal mode.
  2389.      * When we think the terminal is normal, don't try to set it to
  2390.      * normal again, because that causes problems (logout!) on some
  2391.      * machines.
  2392.      */
  2393.     if (tmode != TMODE_COOK || oldtmode != TMODE_COOK)
  2394.     {
  2395.         out_flush();
  2396.         mch_settmode(tmode);    /* machine specific function */
  2397. #ifdef USE_MOUSE
  2398.         if (tmode != TMODE_RAW)
  2399.         mch_setmouse(FALSE);        /* switch mouse off */
  2400.         else
  2401.         setmouse();            /* may switch mouse on */
  2402. #endif
  2403.         out_flush();
  2404.         oldtmode = tmode;
  2405.     }
  2406.     }
  2407. }
  2408.  
  2409.     void
  2410. starttermcap()
  2411. {
  2412.     screen_stop_highlight();
  2413.     if (full_screen && !termcap_active)
  2414.     {
  2415.     out_str(T_TI);            /* start termcap mode */
  2416.     out_str(T_KS);            /* start "keypad transmit" mode */
  2417.     out_flush();
  2418.     termcap_active = TRUE;
  2419.     screen_start();            /* don't know where cursor is now */
  2420.     }
  2421. }
  2422.  
  2423.     void
  2424. stoptermcap()
  2425. {
  2426.     screen_stop_highlight();
  2427.     reset_cterm_colors();
  2428.     if (termcap_active)
  2429.     {
  2430.     out_str(T_KE);            /* stop "keypad transmit" mode */
  2431.     out_flush();
  2432.     termcap_active = FALSE;
  2433.     cursor_on();            /* just in case it is still off */
  2434.     out_str(T_TE);            /* stop termcap mode */
  2435.     screen_start();            /* don't know where cursor is now */
  2436.     out_flush();
  2437.     }
  2438. }
  2439.  
  2440. /*
  2441.  * Return TRUE when saving and restoring the screen.
  2442.  */
  2443.     int
  2444. swapping_screen()
  2445. {
  2446.     return (*T_TI != NUL);
  2447. }
  2448.  
  2449. #ifdef USE_MOUSE
  2450. /*
  2451.  * setmouse() - switch mouse on/off depending on current mode and 'mouse'
  2452.  */
  2453.     void
  2454. setmouse()
  2455. {
  2456.     int        checkfor;
  2457.  
  2458. # ifdef USE_GUI
  2459.     if (gui.in_use)
  2460.     return;
  2461. # endif
  2462.     if (*p_mouse == NUL)        /* be quick when mouse is off */
  2463.     return;
  2464.  
  2465.     if (VIsual_active)
  2466.     checkfor = MOUSE_VISUAL;
  2467.     else if (State == HITRETURN)
  2468.     checkfor = MOUSE_RETURN;
  2469.     else if (State & INSERT)
  2470.     checkfor = MOUSE_INSERT;
  2471.     else if (State & CMDLINE)
  2472.     checkfor = MOUSE_COMMAND;
  2473.     else
  2474.     checkfor = MOUSE_NORMAL;        /* assume normal mode */
  2475.  
  2476.     if (mouse_has(checkfor) || mouse_has(TO_UPPER(checkfor)))
  2477.     mch_setmouse(TRUE);
  2478.     else
  2479.     mch_setmouse(FALSE);
  2480. }
  2481.  
  2482. /*
  2483.  * Return TRUE if
  2484.  * - "c" is in 'mouse', or
  2485.  * - 'a' is in 'mouse' and "c" is in MOUSE_A, or
  2486.  * - 'A' is in 'mouse' and "c" is in MOUSE_A_NV, or
  2487.  * - the current buffer is a help file and 'h' is in 'mouse' and we are in a
  2488.  *   normal editing mode (not at hit-return message).
  2489.  */
  2490.     int
  2491. mouse_has(c)
  2492.     int        c;
  2493. {
  2494.     return (vim_strchr(p_mouse, c) != NULL
  2495.         || (vim_strchr(p_mouse, 'a') != NULL
  2496.             && vim_strchr((char_u *)MOUSE_A, c) != NULL)
  2497.         || (vim_strchr(p_mouse, 'A') != NULL
  2498.             && vim_strchr((char_u *)MOUSE_A_NV, c) != NULL)
  2499.         || (c != MOUSE_RETURN && curbuf->b_help
  2500.             && vim_strchr(p_mouse, MOUSE_HELP)));
  2501. }
  2502. #endif
  2503.  
  2504. /*
  2505.  * By outputting the 'cursor very visible' termcap code, for some windowed
  2506.  * terminals this makes the screen scrolled to the correct position.
  2507.  * Used when starting Vim or returning from a shell.
  2508.  */
  2509.     void
  2510. scroll_start()
  2511. {
  2512.     if (*T_VS != NUL)
  2513.     {
  2514.     out_str(T_VS);
  2515.     out_str(T_VE);
  2516.     screen_start();            /* don't know where cursor is now */
  2517.     }
  2518. }
  2519.  
  2520. /*
  2521.  * enable cursor, unless in Visual mode.
  2522.  */
  2523. static int cursor_is_off = FALSE;
  2524.  
  2525.     void
  2526. cursor_on()
  2527. {
  2528.     if (cursor_is_off && !VIsual_active)
  2529.     {
  2530.     out_str(T_VE);
  2531.     cursor_is_off = FALSE;
  2532.     }
  2533. }
  2534.  
  2535.     void
  2536. cursor_off()
  2537. {
  2538.     if (full_screen)
  2539.     {
  2540.     if (!cursor_is_off)
  2541.         out_str(T_VI);        /* disable cursor */
  2542.     cursor_is_off = TRUE;
  2543.     }
  2544. }
  2545.  
  2546. /*
  2547.  * Set scrolling region for window 'wp'.
  2548.  * The region starts 'off' lines from the start of the window.
  2549.  */
  2550.     void
  2551. scroll_region_set(wp, off)
  2552.     WIN        *wp;
  2553.     int        off;
  2554. {
  2555.     OUT_STR(tgoto((char *)T_CS, wp->w_winpos + wp->w_height - 1,
  2556.                              wp->w_winpos + off));
  2557.     screen_start();            /* don't know where cursor is now */
  2558. }
  2559.  
  2560. /*
  2561.  * Reset scrolling region to the whole screen.
  2562.  */
  2563.     void
  2564. scroll_region_reset()
  2565. {
  2566.     OUT_STR(tgoto((char *)T_CS, (int)Rows - 1, 0));
  2567.     screen_start();            /* don't know where cursor is now */
  2568. }
  2569.  
  2570.  
  2571. /*
  2572.  * List of terminal codes that are currently recognized.
  2573.  */
  2574.  
  2575. struct termcode
  2576. {
  2577.     char_u  name[2];        /* termcap name of entry */
  2578.     char_u  *code;        /* terminal code (in allocated memory) */
  2579.     int        len;        /* STRLEN(code) */
  2580. } *termcodes = NULL;
  2581.  
  2582. static int  tc_max_len = 0; /* number of entries that termcodes[] can hold */
  2583. static int  tc_len = 0;        /* current number of entries in termcodes[] */
  2584.  
  2585.     void
  2586. clear_termcodes()
  2587. {
  2588.     while (tc_len > 0)
  2589.     vim_free(termcodes[--tc_len].code);
  2590.     vim_free(termcodes);
  2591.     termcodes = NULL;
  2592.     tc_max_len = 0;
  2593.  
  2594. #ifdef HAVE_TGETENT
  2595.     BC = (char *)empty_option;
  2596.     UP = (char *)empty_option;
  2597.     PC = NUL;            /* set pad character to NUL */
  2598.     ospeed = 0;
  2599. #endif
  2600.  
  2601.     need_gather = TRUE;        /* need to fill termleader[] */
  2602. }
  2603.  
  2604. /*
  2605.  * Add a new entry to the list of terminal codes.
  2606.  * The list is kept alphabetical for ":set termcap"
  2607.  */
  2608.     void
  2609. add_termcode(name, string)
  2610.     char_u  *name;
  2611.     char_u  *string;
  2612. {
  2613.     struct termcode *new_tc;
  2614.     int            i, j;
  2615.     char_u        *s;
  2616.  
  2617.     if (string == NULL || *string == NUL)
  2618.     {
  2619.     del_termcode(name);
  2620.     return;
  2621.     }
  2622.  
  2623.     s = vim_strsave(string);
  2624.     if (s == NULL)
  2625.     return;
  2626.  
  2627.     need_gather = TRUE;        /* need to fill termleader[] */
  2628.  
  2629.     /*
  2630.      * need to make space for more entries
  2631.      */
  2632.     if (tc_len == tc_max_len)
  2633.     {
  2634.     tc_max_len += 20;
  2635.     new_tc = (struct termcode *)alloc(
  2636.                 (unsigned)(tc_max_len * sizeof(struct termcode)));
  2637.     if (new_tc == NULL)
  2638.     {
  2639.         tc_max_len -= 20;
  2640.         return;
  2641.     }
  2642.     for (i = 0; i < tc_len; ++i)
  2643.         new_tc[i] = termcodes[i];
  2644.     vim_free(termcodes);
  2645.     termcodes = new_tc;
  2646.     }
  2647.  
  2648.     /*
  2649.      * Look for existing entry with the same name, it is replaced.
  2650.      * Look for an existing entry that is alphabetical higher, the new entry
  2651.      * is inserted in front of it.
  2652.      */
  2653.     for (i = 0; i < tc_len; ++i)
  2654.     {
  2655.     if (termcodes[i].name[0] < name[0])
  2656.         continue;
  2657.     if (termcodes[i].name[0] == name[0])
  2658.     {
  2659.         if (termcodes[i].name[1] < name[1])
  2660.         continue;
  2661.         /*
  2662.          * Exact match: Replace old code.
  2663.          */
  2664.         if (termcodes[i].name[1] == name[1])
  2665.         {
  2666.         vim_free(termcodes[i].code);
  2667.         --tc_len;
  2668.         break;
  2669.         }
  2670.     }
  2671.     /*
  2672.      * Found alphabetical larger entry, move rest to insert new entry
  2673.      */
  2674.     for (j = tc_len; j > i; --j)
  2675.         termcodes[j] = termcodes[j - 1];
  2676.     break;
  2677.     }
  2678.  
  2679.     termcodes[i].name[0] = name[0];
  2680.     termcodes[i].name[1] = name[1];
  2681.     termcodes[i].code = s;
  2682.     termcodes[i].len = STRLEN(s);
  2683.     ++tc_len;
  2684. }
  2685.  
  2686.     char_u  *
  2687. find_termcode(name)
  2688.     char_u  *name;
  2689. {
  2690.     int        i;
  2691.  
  2692.     for (i = 0; i < tc_len; ++i)
  2693.     if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
  2694.         return termcodes[i].code;
  2695.     return NULL;
  2696. }
  2697.  
  2698.     char_u *
  2699. get_termcode(i)
  2700.     int        i;
  2701. {
  2702.     if (i >= tc_len)
  2703.     return NULL;
  2704.     return &termcodes[i].name[0];
  2705. }
  2706.  
  2707.     void
  2708. del_termcode(name)
  2709.     char_u  *name;
  2710. {
  2711.     int        i;
  2712.  
  2713.     if (termcodes == NULL)    /* nothing there yet */
  2714.     return;
  2715.  
  2716.     need_gather = TRUE;        /* need to fill termleader[] */
  2717.  
  2718.     for (i = 0; i < tc_len; ++i)
  2719.     if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
  2720.     {
  2721.         vim_free(termcodes[i].code);
  2722.         --tc_len;
  2723.         while (i < tc_len)
  2724.         {
  2725.         termcodes[i] = termcodes[i + 1];
  2726.         ++i;
  2727.         }
  2728.         return;
  2729.     }
  2730.     /* not found. Give error message? */
  2731. }
  2732.  
  2733. /*
  2734.  * Check if typebuf[] contains a terminal key code.
  2735.  * Check from typebuf[typeoff] to typebuf[typeoff + max_offset].
  2736.  * Return 0 for no match, -1 for partial match, > 0 for full match.
  2737.  * With a match, the match is removed, the replacement code is inserted in
  2738.  * typebuf[] and the number of characters in typebuf[] is returned.
  2739.  */
  2740.     int
  2741. check_termcode(max_offset)
  2742.     int        max_offset;
  2743. {
  2744.     char_u    *tp;
  2745.     char_u    *p;
  2746.     int        slen = 0;    /* init for GCC */
  2747.     int        len;
  2748.     int        offset;
  2749.     char_u    key_name[2];
  2750.     int        new_slen;
  2751.     int        extra;
  2752.     char_u    string[MAX_KEY_CODE_LEN + 1];
  2753.     int        i, j;
  2754. #ifdef USE_GUI
  2755.     long_u    val;
  2756. #endif
  2757. #ifdef USE_MOUSE
  2758. # if !defined(UNIX) || defined(XTERM_MOUSE) || defined(USE_GUI)
  2759.     char_u    bytes[3];
  2760.     int        num_bytes;
  2761. # endif
  2762.     int        mouse_code = 0;        /* init for GCC */
  2763.     int        modifiers;
  2764.     int        is_click, is_drag;
  2765.     int        current_button;
  2766.     static int    held_button = MOUSE_RELEASE;
  2767.     static int    orig_num_clicks = 1;
  2768.     static int    orig_mouse_code = 0x0;
  2769. # if defined(UNIX) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
  2770.     static int    orig_mouse_col = 0;
  2771.     static int    orig_mouse_row = 0;
  2772.     static linenr_t orig_topline = 0;
  2773.     static struct timeval  orig_mouse_time = {0, 0};
  2774.                     /* time of previous mouse click */
  2775.     struct timeval  mouse_time;        /* time of current mouse click */
  2776.     long    timediff;        /* elapsed time in msec */
  2777. # endif
  2778. #endif
  2779.  
  2780.     /*
  2781.      * Speed up the checks for terminal codes by gathering all first bytes
  2782.      * used in termleader[].  Often this is just a single <Esc>.
  2783.      */
  2784.     if (need_gather)
  2785.     gather_termleader();
  2786.  
  2787.     /*
  2788.      * Check at several positions in typebuf[], to catch something like
  2789.      * "x<Up>" that can be mapped. Stop at max_offset, because characters
  2790.      * after that cannot be used for mapping, and with @r commands typebuf[]
  2791.      * can become very long.
  2792.      * This is used often, KEEP IT FAST!
  2793.      */
  2794.     for (offset = 0; offset < typelen && offset < max_offset; ++offset)
  2795.     {
  2796.     tp = typebuf + typeoff + offset;
  2797.  
  2798.     /*
  2799.      * Don't check characters after K_SPECIAL, those are already
  2800.      * translated terminal chars (avoid translating ~@^Hx).
  2801.      */
  2802.     if (*tp == K_SPECIAL)
  2803.     {
  2804.         offset += 2;    /* there are always 2 extra characters */
  2805.         continue;
  2806.     }
  2807.  
  2808.     /*
  2809.      * Skip this position if the character does not appear as the first
  2810.      * character in term_strings. This speeds up a lot, since most
  2811.      * termcodes start with the same character (ESC or CSI).
  2812.      */
  2813.     i = *tp;
  2814.     for (p = termleader; *p && *p != i; ++p)
  2815.         ;
  2816.     if (*p == NUL)
  2817.         continue;
  2818.  
  2819.     /*
  2820.      * Skip this position if p_ek is not set and
  2821.      * typebuf[typeoff + offset] is an ESC and we are in insert mode
  2822.      */
  2823.     if (*tp == ESC && !p_ek && (State & INSERT))
  2824.         continue;
  2825.  
  2826.     len = typelen - offset;    /* length of the input */
  2827.     new_slen = 0;        /* Length of what will replace the termcode */
  2828.     key_name[0] = NUL;    /* no key name found yet */
  2829.  
  2830. #ifdef USE_GUI
  2831.     if (gui.in_use)
  2832.     {
  2833.         /*
  2834.          * GUI special key codes are all of the form [CSI xx].
  2835.          */
  2836.         if (*tp == CSI)        /* Special key from GUI */
  2837.         {
  2838.         if (len < 3)
  2839.             return -1;        /* Shouldn't happen */
  2840.         slen = 3;
  2841.         key_name[0] = tp[1];
  2842.         key_name[1] = tp[2];
  2843.         }
  2844.     }
  2845.     else
  2846. #endif /* USE_GUI */
  2847.     {
  2848.         for (i = 0; i < tc_len; ++i)
  2849.         {
  2850.         /*
  2851.          * Ignore the entry if we are not at the start of typebuf[]
  2852.          * and there are not enough characters to make a match.
  2853.          */
  2854.         slen = termcodes[i].len;
  2855.         if (offset && len < slen)
  2856.             continue;
  2857.         if (STRNCMP(termcodes[i].code, tp,
  2858.                      (size_t)(slen > len ? len : slen)) == 0)
  2859.         {
  2860.             if (len < slen)        /* got a partial sequence */
  2861.             return -1;        /* need to get more chars */
  2862.  
  2863.             /*
  2864.              * When found a keypad key, check if there is another key
  2865.              * that matches and use that one.  This makes <Home> to be
  2866.              * found instead of <kHome> when they produce the same
  2867.              * key code.
  2868.              */
  2869.             if (termcodes[i].name[0] == 'K' &&
  2870.                         isdigit(termcodes[i].name[1]))
  2871.             {
  2872.             for (j = i + 1; j < tc_len; ++j)
  2873.                 if (termcodes[j].len == slen &&
  2874.                     STRNCMP(termcodes[i].code,
  2875.                         termcodes[j].code, slen) == 0)
  2876.                 {
  2877.                 i = j;
  2878.                 break;
  2879.                 }
  2880.             }
  2881.  
  2882.             /* replace K_XF1 by K_F1, K_XF1 by K_F2, etc. */
  2883.             if (termcodes[i].name[0] == KS_EXTRA)
  2884.             switch (termcodes[i].name[1])
  2885.             {
  2886.                 case KE_XF1: termcodes[i].name[0] = 'k';
  2887.                      termcodes[i].name[1] = '1';
  2888.                      break;
  2889.                 case KE_XF2: termcodes[i].name[0] = 'k';
  2890.                      termcodes[i].name[1] = '2';
  2891.                      break;
  2892.                 case KE_XF3: termcodes[i].name[0] = 'k';
  2893.                      termcodes[i].name[1] = '3';
  2894.                      break;
  2895.                 case KE_XF4: termcodes[i].name[0] = 'k';
  2896.                      termcodes[i].name[1] = '4';
  2897.                      break;
  2898.             }
  2899.  
  2900.             key_name[0] = termcodes[i].name[0];
  2901.             key_name[1] = termcodes[i].name[1];
  2902.  
  2903.             break;
  2904.         }
  2905.         }
  2906.     }
  2907.  
  2908.     if (key_name[0] == NUL)
  2909.         continue;        /* No match at this position, try next one */
  2910.  
  2911.     /* We only get here when we have a complete termcode match */
  2912.  
  2913. #ifdef USE_MOUSE
  2914.     /*
  2915.      * If it is a mouse click, get the coordinates.
  2916.      */
  2917.     if (key_name[0] == (int)KS_MOUSE
  2918. # ifdef NETTERM_MOUSE
  2919.         || key_name[0] == (int)KS_NETTERM_MOUSE
  2920. # endif
  2921. # ifdef DEC_MOUSE
  2922.         || key_name[0] == (int)KS_DEC_MOUSE
  2923. # endif
  2924.         )
  2925.     {
  2926.         is_click = is_drag = FALSE;
  2927.  
  2928. #if !defined(UNIX) || defined(XTERM_MOUSE)
  2929.         if (key_name[0] == (int)KS_MOUSE)
  2930.         {
  2931.         /*
  2932.          * For xterm and MSDOS we get "<t_mouse>scr", where
  2933.          *  s == encoded button state (0x20 = left, 0x22 = right, etc.)
  2934.          *  c == column + ' ' + 1 == column + 33
  2935.          *  r == row + ' ' + 1 == row + 33
  2936.          *
  2937.          * The coordinates are passed on through global variables. Ugly,
  2938.          * but this avoids trouble with mouse clicks at an unexpected
  2939.          * moment and allows for mapping them.
  2940.          */
  2941.         num_bytes = get_bytes_from_buf(tp + slen, bytes, 3);
  2942.         if (num_bytes == -1)    /* not enough coordinates */
  2943.             return -1;
  2944.         mouse_code = bytes[0];
  2945.         mouse_col = bytes[1] - ' ' - 1;
  2946.         mouse_row = bytes[2] - ' ' - 1;
  2947.         slen += num_bytes;
  2948.         }
  2949. #endif /* !UNIX || XTERM_MOUSE */
  2950. #ifdef NETTERM_MOUSE
  2951.         if (key_name[0] == (int)KS_NETTERM_MOUSE)
  2952.         {
  2953.         int mc, mr;
  2954.  
  2955.         /* expect a rather limited sequence like: balancing {
  2956.          * \033}6,45\r
  2957.          * '6' is the row, 45 is the column
  2958.          */
  2959.         p = tp + slen;
  2960.         mr = getdigits(&p);
  2961.         if (*p++ != ',')
  2962.             return -1;
  2963.         mc = getdigits(&p);
  2964.         if (*p++ != '\r')
  2965.             return -1;
  2966.  
  2967.         mouse_col = mc - 1;
  2968.         mouse_row = mr - 1;
  2969.         mouse_code = MOUSE_LEFT;
  2970.         slen += (p - (tp + slen));
  2971.         }
  2972. #endif    /* NETTERM_MOUSE */
  2973. #ifdef DEC_MOUSE
  2974.         if (key_name[0] == (int)KS_DEC_MOUSE)
  2975.         {
  2976.            /* The DEC Locator Input Model
  2977.         * Netterm delivers the code sequence:
  2978.         *  \033[2;4;24;80&w  (left button down)
  2979.         *  \033[3;0;24;80&w  (left button up)
  2980.         *  \033[6;1;24;80&w  (right button down)
  2981.         *  \033[7;0;24;80&w  (right button up)
  2982.         * CSI Pe ; Pb ; Pr ; Pc ; Pp & w
  2983.         * Pe is the event code
  2984.         * Pb is the button code
  2985.         * Pr is the row coordinate
  2986.         * Pc is the column coordinate
  2987.         * Pp is the third coordinate (page number)
  2988.         * Pe, the event code indicates what event caused this report
  2989.         *    The following event codes are defined:
  2990.         *    0 - request, the terminal received an explicit request
  2991.         *     for a locator report, but the locator is unavailable
  2992.         *    1 - request, the terminal received an explicit request
  2993.         *     for a locator report
  2994.         *    2 - left button down
  2995.         *    3 - left button up
  2996.         *    4 - middle button down
  2997.         *    5 - middle button up
  2998.         *    6 - right button down
  2999.         *    7 - right button up
  3000.         *    8 - fourth button down
  3001.         *    9 - fourth button up
  3002.         *    10 - locator outside filter rectangle
  3003.         * Pb, the button code, ASCII decimal 0-15 indicating which
  3004.         *   buttons are down if any. The state of the four buttons
  3005.         *   on the locator correspond to the low four bits of the
  3006.         *   decimal value,
  3007.         *   "1" means button depressed
  3008.         *   0 - no buttons down,
  3009.         *   1 - right,
  3010.         *   2 - middle,
  3011.         *   4 - left,
  3012.         *   8 - fourth
  3013.         * Pr is the row coordinate of the locator position in the page,
  3014.         *   encoded as an ASCII decimal value.
  3015.         *   If Pr is omitted, the locator position is undefined
  3016.         *   (outside the terminal window for example).
  3017.         * Pc is the column coordinate of the locator position in the
  3018.         *   page, encoded as an ASCII decimal value.
  3019.         *   If Pc is omitted, the locator position is undefined
  3020.         *   (outside the terminal window for example).
  3021.         * Pp is the page coordinate of the locator position
  3022.         *   encoded as an ASCII decimal value.
  3023.         *   The page coordinate may be omitted if the locator is on
  3024.         *   page one (the default).
  3025.         */
  3026.         int Pe, Pb, Pr, Pc, Pp;
  3027.  
  3028.         p = tp + slen;
  3029.  
  3030.         /* get event status */
  3031.         Pe = getdigits(&p);
  3032.         if (*p++ != ';')
  3033.             return -1;
  3034.  
  3035.         /* get button status */
  3036.         Pb = getdigits(&p);
  3037.         if (*p++ != ';')
  3038.             return -1;
  3039.  
  3040.         /* get row status */
  3041.         Pr = getdigits(&p);
  3042.         if (*p++ != ';')
  3043.             return -1;
  3044.  
  3045.         /* get column status */
  3046.         Pc = getdigits(&p);
  3047.  
  3048.         /* the page parameter is optional */
  3049.         if (*p == ';')
  3050.         {
  3051.             p++;
  3052.             Pp = getdigits(&p);
  3053.         }
  3054.         else
  3055.             Pp = 0;
  3056.         if (*p++ != '&')
  3057.             return -1;
  3058.         if (*p++ != 'w')
  3059.             return -1;
  3060.  
  3061.         mouse_code = 0;
  3062.         switch (Pe)
  3063.         {
  3064.         case  0: return -1; /* position request while unavailable */
  3065.         case  1: /* a response to a locator position request includes
  3066.                 the status of all buttons */
  3067.              Pb &= 7;   /* mask off and ignore fourth button */
  3068.              if (Pb & 4)
  3069.                  mouse_code  = MOUSE_LEFT;
  3070.              if (Pb & 2)
  3071.                  mouse_code  = MOUSE_MIDDLE;
  3072.              if (Pb & 1)
  3073.                  mouse_code  = MOUSE_RIGHT;
  3074.              if (Pb)
  3075.              {
  3076.                  held_button = mouse_code;
  3077.                  mouse_code |= MOUSE_DRAG;
  3078.                  WantQueryMouse = 1;
  3079.              }
  3080.              is_drag = TRUE;
  3081.              showmode();
  3082.              break;
  3083.         case  2: mouse_code = MOUSE_LEFT;
  3084.              WantQueryMouse = 1;
  3085.              break;
  3086.         case  3: mouse_code = MOUSE_RELEASE | MOUSE_LEFT;
  3087.              break;
  3088.         case  4: mouse_code = MOUSE_MIDDLE;
  3089.              WantQueryMouse = 1;
  3090.              break;
  3091.         case  5: mouse_code = MOUSE_RELEASE | MOUSE_MIDDLE;
  3092.              break;
  3093.         case  6: mouse_code = MOUSE_RIGHT;
  3094.              WantQueryMouse = 1;
  3095.              break;
  3096.         case  7: mouse_code = MOUSE_RELEASE | MOUSE_RIGHT;
  3097.              break;
  3098.         case  8: return -1; /* fourth button down */
  3099.         case  9: return -1; /* fourth button up */
  3100.         case 10: return -1; /* mouse outside of filter rectangle */
  3101.         default: return -1; /* should never occur */
  3102.         }
  3103.  
  3104.         /* we ignore the Pp word */
  3105.         mouse_col = Pc - 1;
  3106.         mouse_row = Pr - 1;
  3107.  
  3108.         slen += (p - (tp + slen));
  3109.         }
  3110. #endif /* DEC_MOUSE */
  3111.  
  3112.         /* Interpret the mouse code */
  3113.         current_button = (mouse_code & MOUSE_CLICK_MASK);
  3114.         if (current_button == MOUSE_RELEASE)
  3115.         {
  3116.         /*
  3117.          * If we get a mouse drag or release event when
  3118.          * there is no mouse button held down (held_button ==
  3119.          * MOUSE_RELEASE), produce a K_IGNORE below.
  3120.          * (can happen when you hold down two buttons
  3121.          * and then let them go, or click in the menu bar, but not
  3122.          * on a menu, and drag into the text).
  3123.          */
  3124.         if ((mouse_code & MOUSE_DRAG) == MOUSE_DRAG)
  3125.             is_drag = TRUE;
  3126.         current_button = held_button;
  3127.         }
  3128.         else
  3129.         {
  3130. #if defined(UNIX) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
  3131. # ifdef USE_GUI
  3132.         /*
  3133.          * Only for Unix, when GUI is not active, we handle
  3134.          * multi-clicks here.
  3135.          */
  3136.         if (!gui.in_use)
  3137. # endif
  3138.         {
  3139.             /*
  3140.              * Compute the time elapsed since the previous mouse click.
  3141.              */
  3142.             gettimeofday(&mouse_time, NULL);
  3143.             timediff = (mouse_time.tv_usec -
  3144.                           orig_mouse_time.tv_usec) / 1000;
  3145.             if (timediff < 0)
  3146.             --orig_mouse_time.tv_sec;
  3147.             timediff += (mouse_time.tv_sec -
  3148.                            orig_mouse_time.tv_sec) * 1000;
  3149.             orig_mouse_time = mouse_time;
  3150.             if (mouse_code == orig_mouse_code &&
  3151.                 timediff < p_mouset &&
  3152.                 orig_num_clicks != 4 &&
  3153.                 orig_mouse_col == mouse_col &&
  3154.                 orig_mouse_row == mouse_row &&
  3155.                 orig_topline == curwin->w_topline)
  3156.             ++orig_num_clicks;
  3157.             else
  3158.             orig_num_clicks = 1;
  3159.             orig_mouse_col = mouse_col;
  3160.             orig_mouse_row = mouse_row;
  3161.             orig_topline = curwin->w_topline;
  3162.         }
  3163. # ifdef USE_GUI
  3164.         else
  3165.             orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
  3166. # endif
  3167. #else
  3168.         orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
  3169. #endif
  3170.         is_click = TRUE;
  3171.         orig_mouse_code = mouse_code;
  3172.         }
  3173.         if (!is_drag)
  3174.         held_button = mouse_code & MOUSE_CLICK_MASK;
  3175.  
  3176.         /*
  3177.          * Translate the actual mouse event into a pseudo mouse event.
  3178.          * First work out what modifiers are to be used.
  3179.          */
  3180.         modifiers = 0x0;
  3181.         if (orig_mouse_code & MOUSE_SHIFT)
  3182.         modifiers |= MOD_MASK_SHIFT;
  3183.         if (orig_mouse_code & MOUSE_CTRL)
  3184.         modifiers |= MOD_MASK_CTRL;
  3185.         if (orig_mouse_code & MOUSE_ALT)
  3186.         modifiers |= MOD_MASK_ALT;
  3187.         if (orig_num_clicks == 2)
  3188.         modifiers |= MOD_MASK_2CLICK;
  3189.         else if (orig_num_clicks == 3)
  3190.         modifiers |= MOD_MASK_3CLICK;
  3191.         else if (orig_num_clicks == 4)
  3192.         modifiers |= MOD_MASK_4CLICK;
  3193.  
  3194.         /* Add the modifier codes to our string */
  3195.         if (modifiers != 0)
  3196.         {
  3197.         string[new_slen++] = K_SPECIAL;
  3198.         string[new_slen++] = (int)KS_MODIFIER;
  3199.         string[new_slen++] = modifiers;
  3200.         }
  3201.  
  3202.         /* Work out our pseudo mouse event */
  3203.         key_name[0] = (int)KS_EXTRA;
  3204.         key_name[1] = get_pseudo_mouse_code(current_button,
  3205.                                is_click, is_drag);
  3206.     }
  3207. #endif /* USE_MOUSE */
  3208.  
  3209. #ifdef USE_GUI
  3210.     /*
  3211.      * If using the GUI, then we get menu and scrollbar events.
  3212.      *
  3213.      * A menu event is encoded as K_SPECIAL, KS_MENU, K_FILLER followed by
  3214.      * four bytes which are to be taken as a pointer to the GuiMenu
  3215.      * structure.
  3216.      *
  3217.      * A scrollbar event is K_SPECIAL, KS_SCROLLBAR, K_FILLER followed by
  3218.      * one byte representing the scrollbar number, and then four bytes
  3219.      * representing a long_u which is the new value of the scrollbar.
  3220.      *
  3221.      * A horizontal scrollbar event is K_SPECIAL, KS_HORIZ_SCROLLBAR,
  3222.      * K_FILLER followed by four bytes representing a long_u which is the
  3223.      * new value of the scrollbar.
  3224.      */
  3225.     else if (key_name[0] == (int)KS_MENU)
  3226.     {
  3227.         num_bytes = get_long_from_buf(tp + slen, &val);
  3228.         if (num_bytes == -1)
  3229.         return -1;
  3230.         current_menu = (GuiMenu *)val;
  3231.         slen += num_bytes;
  3232.     }
  3233.     else if (key_name[0] == (int)KS_SCROLLBAR)
  3234.     {
  3235.         /* Get the last scrollbar event in the queue of the same type */
  3236.         j = 0;
  3237.         for (i = 0; tp[j] == CSI && tp[j+1] == KS_SCROLLBAR
  3238.                             && tp[j+2] != NUL; ++i)
  3239.         {
  3240.         j += 3;
  3241.         num_bytes = get_bytes_from_buf(tp + j, bytes, 1);
  3242.         if (num_bytes == -1)
  3243.             break;
  3244.         if (i == 0)
  3245.             current_scrollbar = (int)bytes[0];
  3246.         else if (current_scrollbar != (int)bytes[0])
  3247.             break;
  3248.         j += num_bytes;
  3249.         num_bytes = get_long_from_buf(tp + j, &val);
  3250.         if (num_bytes == -1)
  3251.             break;
  3252.         scrollbar_value = val;
  3253.         j += num_bytes;
  3254.         slen = j;
  3255.         }
  3256.         if (i == 0)        /* not enough characters to make one */
  3257.         return -1;
  3258.     }
  3259.     else if (key_name[0] == (int)KS_HORIZ_SCROLLBAR)
  3260.     {
  3261.         /* Get the last horiz. scrollbar event in the queue */
  3262.         j = 0;
  3263.         for (i = 0; tp[j] == CSI && tp[j+1] == KS_HORIZ_SCROLLBAR
  3264.                                && tp[j+2] != NUL; ++i)
  3265.         {
  3266.         j += 3;
  3267.         num_bytes = get_long_from_buf(tp + j, &val);
  3268.         if (num_bytes == -1)
  3269.             break;
  3270.         scrollbar_value = val;
  3271.         j += num_bytes;
  3272.         slen = j;
  3273.         }
  3274.         if (i == 0)        /* not enough characters to make one */
  3275.         return -1;
  3276.     }
  3277. #endif /* USE_GUI */
  3278.     /* Finally, add the special key code to our string */
  3279.     if (key_name[1] == NUL)
  3280.         string[new_slen++] = key_name[0];    /* from ":set <M-b>=xx" */
  3281.     else
  3282.     {
  3283.         string[new_slen++] = K_SPECIAL;
  3284.         string[new_slen++] = key_name[0];
  3285.         string[new_slen++] = key_name[1];
  3286.     }
  3287.     string[new_slen] = NUL;
  3288.     extra = new_slen - slen;
  3289.     if (extra < 0)
  3290.         /* remove matched chars, taking care of noremap */
  3291.         del_typebuf(-extra, offset);
  3292.     else if (extra > 0)
  3293.         /* insert the extra space we need */
  3294.         ins_typebuf(string + slen, FALSE, offset, FALSE);
  3295.  
  3296.     /*
  3297.      * Careful: del_typebuf() and ins_typebuf() may have
  3298.      * reallocated typebuf[]
  3299.      */
  3300.     vim_memmove(typebuf + typeoff + offset, string, (size_t)new_slen);
  3301.     return (len + extra + offset);
  3302.     }
  3303.     return 0;                /* no match found */
  3304. }
  3305.  
  3306. /*
  3307.  * Replace any terminal code strings in from[] with the equivalent internal
  3308.  * vim representation.    This is used for the "from" and "to" part of a
  3309.  * mapping, and the "to" part of a menu command.
  3310.  * Any strings like "<C-UP>" are also replaced, unless 'cpoptions' contains
  3311.  * '<'.
  3312.  * K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL K_FILLER.
  3313.  *
  3314.  * The replacement is done in result[] and finally copied into allocated
  3315.  * memory. If this all works well *bufp is set to the allocated memory and a
  3316.  * pointer to it is returned. If something fails *bufp is set to NULL and from
  3317.  * is returned.
  3318.  *
  3319.  * CTRL-V characters are removed.  When "from_part" is TRUE, a trailing CTRL-V
  3320.  * is included, otherwise it is removed (for ":map xx ^V", maps xx to
  3321.  * nothing).  When 'cpoptions' does not contain 'B', a backslash can be used
  3322.  * instead of a CTRL-V.
  3323.  */
  3324.     char_u  *
  3325. replace_termcodes(from, bufp, from_part)
  3326.     char_u  *from;
  3327.     char_u  **bufp;
  3328.     int        from_part;
  3329. {
  3330.     int        i;
  3331.     int        slen;
  3332.     int        key;
  3333.     int        dlen = 0;
  3334.     char_u  *src;
  3335.     int        do_backslash;    /* backslash is a special character */
  3336.     int        do_special;        /* recognize <> key codes */
  3337.     int        do_key_code;    /* recognize raw key codes */
  3338.     char_u  *result;        /* buffer for resulting string */
  3339.  
  3340.     do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
  3341.     do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL);
  3342.     do_key_code = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL);
  3343.  
  3344.     /*
  3345.      * Allocate space for the translation.  Worst case a single character is
  3346.      * replaced by 6 bytes (shifted special key), plus a NUL at the end.
  3347.      */
  3348.     result = alloc((unsigned)STRLEN(from) * 6 + 1);
  3349.     if (result == NULL)        /* out of memory */
  3350.     {
  3351.     *bufp = NULL;
  3352.     return from;
  3353.     }
  3354.  
  3355.     src = from;
  3356.  
  3357.     /*
  3358.      * Check for #n at start only: function key n
  3359.      */
  3360.     if (from_part && src[0] == '#' && isdigit(src[1]))        /* function key */
  3361.     {
  3362.     result[dlen++] = K_SPECIAL;
  3363.     result[dlen++] = 'k';
  3364.     if (src[1] == '0')
  3365.         result[dlen++] = ';';    /* #0 is F10 is "k;" */
  3366.     else
  3367.         result[dlen++] = src[1];    /* #3 is F3 is "k3" */
  3368.     src += 2;
  3369.     }
  3370.  
  3371.     /*
  3372.      * Copy each byte from *from to result[dlen]
  3373.      */
  3374.     while (*src != NUL)
  3375.     {
  3376.     /*
  3377.      * If 'cpoptions' does not contain '<', check for special key codes,
  3378.      * like "<C-S-MouseLeft>"
  3379.      */
  3380.     if (do_special)
  3381.     {
  3382.         slen = trans_special(&src, result + dlen);
  3383.         if (slen)
  3384.         {
  3385.         dlen += slen;
  3386.         continue;
  3387.         }
  3388.     }
  3389.  
  3390.     /*
  3391.      * If 'cpoptions' does not contain 'k', see if it's an actual key-code.
  3392.      * Note that this is also checked after replacing the <> form.
  3393.      * Single character codes are NOT replaced (e.g. ^H or DEL), because
  3394.      * it could be a character in the file.
  3395.      */
  3396.     if (do_key_code)
  3397.     {
  3398.         for (i = 0; i < tc_len; ++i)
  3399.         {
  3400.         slen = termcodes[i].len;
  3401.         if (slen > 1
  3402.             && STRNCMP(termcodes[i].code, src, (size_t)slen) == 0)
  3403.         {
  3404.             result[dlen++] = K_SPECIAL;
  3405.             result[dlen++] = termcodes[i].name[0];
  3406.             result[dlen++] = termcodes[i].name[1];
  3407.             src += slen;
  3408.             break;
  3409.         }
  3410.         }
  3411.  
  3412.         /* If terminal code matched, continue after it. */
  3413.         if (i != tc_len)
  3414.         continue;
  3415.     }
  3416.  
  3417.     /*
  3418.      * If the character is K_SPECIAL, replace it with K_SPECIAL KS_SPECIAL
  3419.      * K_FILLER.
  3420.      */
  3421.     if (*src == K_SPECIAL)
  3422.     {
  3423.         result[dlen++] = K_SPECIAL;
  3424.         result[dlen++] = (int)KS_SPECIAL;
  3425.         result[dlen++] = K_FILLER;
  3426.         ++src;
  3427.         continue;
  3428.     }
  3429.  
  3430.     /*
  3431.      * Remove CTRL-V and ignore the next character.
  3432.      * For "from" side the CTRL-V at the end is included, for the "to"
  3433.      * part it is removed.
  3434.      * If 'cpoptions' does not contain 'B', also accept a backslash.
  3435.      */
  3436.     key = *src;
  3437.     if (key == Ctrl('V') || (do_backslash && key == '\\'))
  3438.     {
  3439.         ++src;                /* skip CTRL-V or backslash */
  3440.         if (*src == NUL)
  3441.         {
  3442.         if (from_part)
  3443.             result[dlen++] = key;
  3444.         break;
  3445.         }
  3446.     }
  3447.     result[dlen++] = *src++;
  3448.     }
  3449.     result[dlen] = NUL;
  3450.  
  3451.     /*
  3452.      * Copy the new string to allocated memory.
  3453.      * If this fails, just return from.
  3454.      */
  3455.     if ((*bufp = vim_strsave(result)) != NULL)
  3456.     from = *bufp;
  3457.     vim_free(result);
  3458.     return from;
  3459. }
  3460.  
  3461. /*
  3462.  * Gather the first characters in the terminal key codes into a string.
  3463.  * Used to speed up check_termcode().
  3464.  */
  3465.     static void
  3466. gather_termleader()
  3467. {
  3468.     int        i;
  3469.     int        len = 0;
  3470.  
  3471. #ifdef USE_GUI
  3472.     if (gui.in_use)
  3473.     termleader[len++] = CSI;    /* the GUI codes are not in termcodes[] */
  3474. #endif
  3475.     termleader[len] = NUL;
  3476.  
  3477.     for (i = 0; i < tc_len; ++i)
  3478.     if (vim_strchr(termleader, termcodes[i].code[0]) == NULL)
  3479.     {
  3480.         termleader[len++] = termcodes[i].code[0];
  3481.         termleader[len] = NUL;
  3482.     }
  3483.  
  3484.     need_gather = FALSE;
  3485. }
  3486.  
  3487. /*
  3488.  * Show all termcodes (for ":set termcap")
  3489.  * This code looks a lot like showoptions(), but is different.
  3490.  */
  3491.     void
  3492. show_termcodes()
  3493. {
  3494.     int            col;
  3495.     int            *items;
  3496.     int            item_count;
  3497.     int            run;
  3498.     int            row, rows;
  3499.     int            cols;
  3500.     int            i;
  3501.     int            len;
  3502.  
  3503. #define INC 27        /* try to make three columns */
  3504. #define GAP 2        /* spaces between columns */
  3505.  
  3506.     if (tc_len == 0)        /* no terminal codes (must be GUI) */
  3507.     return;
  3508.     items = (int *)alloc((unsigned)(sizeof(int) * tc_len));
  3509.     if (items == NULL)
  3510.     return;
  3511.  
  3512.     /* Highlight title */
  3513.     MSG_PUTS_TITLE("\n--- Terminal keys ---");
  3514.  
  3515.     /*
  3516.      * do the loop two times:
  3517.      * 1. display the short items (non-strings and short strings)
  3518.      * 2. display the long items (strings)
  3519.      */
  3520.     for (run = 1; run <= 2 && !got_int; ++run)
  3521.     {
  3522.     /*
  3523.      * collect the items in items[]
  3524.      */
  3525.     item_count = 0;
  3526.     for (i = 0; i < tc_len; i++)
  3527.     {
  3528.         len = show_one_termcode(termcodes[i].name,
  3529.                             termcodes[i].code, FALSE);
  3530.         if ((len <= INC - GAP && run == 1) || (len > INC - GAP && run == 2))
  3531.         items[item_count++] = i;
  3532.     }
  3533.  
  3534.     /*
  3535.      * display the items
  3536.      */
  3537.     if (run == 1)
  3538.     {
  3539.         cols = (Columns + GAP) / INC;
  3540.         if (cols == 0)
  3541.         cols = 1;
  3542.         rows = (item_count + cols - 1) / cols;
  3543.     }
  3544.     else    /* run == 2 */
  3545.         rows = item_count;
  3546.     for (row = 0; row < rows && !got_int; ++row)
  3547.     {
  3548.         msg_putchar('\n');            /* go to next line */
  3549.         if (got_int)            /* 'q' typed in more */
  3550.         break;
  3551.         col = 0;
  3552.         for (i = row; i < item_count; i += rows)
  3553.         {
  3554.         msg_col = col;            /* make columns */
  3555.         show_one_termcode(termcodes[items[i]].name,
  3556.                           termcodes[items[i]].code, TRUE);
  3557.         col += INC;
  3558.         }
  3559.         out_flush();
  3560.         ui_breakcheck();
  3561.     }
  3562.     }
  3563.     vim_free(items);
  3564. }
  3565.  
  3566. /*
  3567.  * Show one termcode entry.
  3568.  * Output goes into IObuff[]
  3569.  */
  3570.     int
  3571. show_one_termcode(name, code, printit)
  3572.     char_u  *name;
  3573.     char_u  *code;
  3574.     int        printit;
  3575. {
  3576.     char_u    *p;
  3577.     int        len;
  3578.  
  3579.     if (name[0] > '~')
  3580.     {
  3581.     IObuff[0] = ' ';
  3582.     IObuff[1] = ' ';
  3583.     IObuff[2] = ' ';
  3584.     IObuff[3] = ' ';
  3585.     }
  3586.     else
  3587.     {
  3588.     IObuff[0] = 't';
  3589.     IObuff[1] = '_';
  3590.     IObuff[2] = name[0];
  3591.     IObuff[3] = name[1];
  3592.     }
  3593.     IObuff[4] = ' ';
  3594.  
  3595.     p = get_special_key_name(TERMCAP2KEY(name[0], name[1]), 0);
  3596.     if (p[1] != 't')
  3597.     STRCPY(IObuff + 5, p);
  3598.     else
  3599.     IObuff[5] = NUL;
  3600.     len = STRLEN(IObuff);
  3601.     do
  3602.     IObuff[len++] = ' ';
  3603.     while (len < 17);
  3604.     IObuff[len] = NUL;
  3605.     if (code == NULL)
  3606.     len += 4;
  3607.     else
  3608.     len += vim_strsize(code);
  3609.  
  3610.     if (printit)
  3611.     {
  3612.     msg_puts(IObuff);
  3613.     if (code == NULL)
  3614.         msg_puts((char_u *)"NULL");
  3615.     else
  3616.         msg_outtrans(code);
  3617.     }
  3618.     return len;
  3619. }
  3620.  
  3621. #if (defined(WIN32) && !defined(USE_GUI)) || defined(PROTO)
  3622. static char ksme_str[20];
  3623. static char ksmr_str[20];
  3624. static char ksmd_str[20];
  3625.  
  3626. /*
  3627.  * For Win32 console: update termcap codes for existing console attributes.
  3628.  */
  3629.     void
  3630. update_tcap(attr)
  3631.     int attr;
  3632. {
  3633.     struct builtin_term *p;
  3634.  
  3635.     p = find_builtin_term(DEFAULT_TERM);
  3636.     sprintf(ksme_str, "\033|%dm", attr);
  3637.     sprintf(ksmd_str, "\033|%dm", attr | 0x08);  /* FOREGROUND_INTENSITY */
  3638.     sprintf(ksmr_str, "\033|%dm", ((attr & 0x0F) << 4) | ((attr & 0xF0) >> 4));
  3639.  
  3640.     while (p->bt_string != NULL)
  3641.     {
  3642.       if (p->bt_entry == (int)KS_ME)
  3643.           p->bt_string = &ksme_str[0];
  3644.       else if (p->bt_entry == (int)KS_MR)
  3645.           p->bt_string = &ksmr_str[0];
  3646.       else if (p->bt_entry == (int)KS_MD)
  3647.           p->bt_string = &ksmd_str[0];
  3648.       ++p;
  3649.     }
  3650. }
  3651. #endif
  3652.